Compare commits
75 Commits
5df79dcce8
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b046046251 | |||
| f4d72122d3 | |||
| 5637fc2fa5 | |||
| b9a14bcb9c | |||
| 04a7d0565d | |||
| 6de489950c | |||
| 09ddeabb1c | |||
| 93a2718e6d | |||
| 40a112a42d | |||
| d3268a69bc | |||
| a96b6a6eef | |||
| 2dfbef40dc | |||
| 1c42ae0af4 | |||
| b9eba29ebe | |||
| 13b4f65723 | |||
| c5b0ce3a25 | |||
| f88b2b9a5b | |||
| 8df728cf8b | |||
| 0684485107 | |||
| be37c2c99c | |||
| 837b455687 | |||
| e21512240f | |||
| 8421d7ba7f | |||
| ec51097277 | |||
| 117f2fb88a | |||
| c6216e006e | |||
| d0c2af8a31 | |||
| 8fa842888a | |||
| 89695721f4 | |||
| c599a9c053 | |||
| b35e62c880 | |||
| 54d97c0349 | |||
| 4d1179f8e5 | |||
| bd09073229 | |||
| 26d2c205c9 | |||
| 4666262c92 | |||
| 72bf63cd04 | |||
| 05d91a05c6 | |||
| 5f944e8bfa | |||
| 1d3e75803f | |||
| f4b48d9c20 | |||
| d350119993 | |||
| 48f15c1da1 | |||
| 5f3a17c5c7 | |||
| a290a51276 | |||
| fc1af63014 | |||
| a07b89e5e1 | |||
| e75fc365c5 | |||
| 5eb1f7ef40 | |||
| 6aebd474fc | |||
| 71f661092d | |||
| e4f8736543 | |||
| 006b58f644 | |||
| 6bef1e26ee | |||
| 80726b603e | |||
| c4d869921d | |||
| 20323d22b3 | |||
| 974716fd85 | |||
| 189e0a694e | |||
| f789ace574 | |||
| 742e0561b5 | |||
| 521993bf85 | |||
| 7abec07549 | |||
| 5c8a201438 | |||
| 4342aae78c | |||
| 859e67e874 | |||
| ebb20fab7e | |||
| 832fea4913 | |||
| 704e25e190 | |||
| 3421cc39d2 | |||
| e18784358b | |||
| 69884c0a50 | |||
| 0df20461e2 | |||
| 31a157cb55 | |||
| a5b3b29307 |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -118,6 +118,9 @@ utile/hpdf/hpdferr.FPT
|
||||
# --- SVN (COMUN este si working copy SVN) ---
|
||||
.svn/
|
||||
|
||||
# --- notite neversionate in git (credentiale) - raman doar in SVN ---
|
||||
docs/local/
|
||||
|
||||
# --- Windows / stare locala ---
|
||||
*.lnk
|
||||
Thumbs.db
|
||||
@@ -126,6 +129,9 @@ bash.exe.stackdump
|
||||
.claude/
|
||||
|
||||
# --- artefacte generate de rularile de test headless ---
|
||||
utile/Teste/**/screenshots/
|
||||
utile/Teste/**/uisync/
|
||||
# (numele reale poarta sufixul scenariului: screenshots_total/, uisync_212/, ...)
|
||||
utile/Teste/**/screenshots*/
|
||||
utile/Teste/**/uisync*/
|
||||
utile/Teste/**/*_log.txt
|
||||
utile/Teste/**/watchdog_out/
|
||||
utile/Teste/**/*_dialog*.png
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2432,6 +2432,9 @@ DEFINE CLASS afisjurcom AS _frmbase OF "_frm_base.vcx"
|
||||
*Select a.*,Iif(Isnull(id_jtva_coloana),0,1) As cu_Tva From tact a Into Cursor tact Readwrite
|
||||
Select a.*,Iif(Nvl(id_jtva_coloana,0)=0,0,1) As cu_Tva From tact a Into Cursor tact Readwrite
|
||||
*!* modificare ROACONT v 2.0.78 ^
|
||||
IF "OFACTURARE_EDITARE" $ Upper(Set("Procedure"))
|
||||
PregatesteArticoleFacturaEditare('tact')
|
||||
ENDIF
|
||||
* Omodif = Createobject([frm_modific2007],lnIdSet)
|
||||
Omodif = Createobject([frm_modific2024],lnIdSet)
|
||||
* DO FORM frm_modific2024 NAME omodif LINKED WITH m.lnIdSet NOSHOW
|
||||
@@ -2485,6 +2488,9 @@ DEFINE CLASS afisjurcom AS _frmbase OF "_frm_base.vcx"
|
||||
ALLTRIM(Str(lnCod)) + [,] + Alltrim(Str(lnIdFact)) + [,] + Alltrim(Str(lnIdfactd)) + [,?gnIdUtil); end;]
|
||||
lnSucces = Iif(goExecutor.oExecuta(lcSql),1,-1)
|
||||
Endif
|
||||
If lnSucces > 0 And "OFACTURARE_EDITARE" $ Upper(Set("Procedure")) And Used('tvanz') And Reccount('tvanz') = 1
|
||||
lnSucces = Iif(ScrieArticoleFacturaEditate(tvanz.id_vanzare), 1, -1)
|
||||
Endif
|
||||
*!* IF lnSucces > 0 AND llGestInvantar && nota de inventariere : update dataOra_validat cu dataora modificarii notei contabile
|
||||
*!* lcSql = [update ] + gcs + [.gest_inventar set dataora_validat = pack_contafin.GET_DATAORA() where dataora_validat = ?pdDataOra and an = ?pnAn and luna = ?pnLuna]
|
||||
*!* lnSucces = goExecutor.oExecute(lcSql)
|
||||
@@ -2558,6 +2564,9 @@ DEFINE CLASS afisjurcom AS _frmbase OF "_frm_base.vcx"
|
||||
If Used('trul_obinv')
|
||||
Use In trul_obinv
|
||||
Endif
|
||||
If Used('crsArticoleFactura')
|
||||
Use In crsArticoleFactura
|
||||
Endif
|
||||
|
||||
|
||||
ENDPROC
|
||||
|
||||
@@ -1131,8 +1131,10 @@ DEFINE CLASS frm_articol_factura AS _frmbase OF "_frm_base.vcx"
|
||||
*< OBJECTDATA: ObjPath="Clb_serie" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="Ed_tx_explicatie" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="cb_explicatie_saft" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="ck_pret_cu_tva" UniqueID="" Timestamp="" />
|
||||
|
||||
*<DefinedPropArrayMethod>
|
||||
*m: do_aplica_mod_pret
|
||||
*m: do_calculeaza_adaos
|
||||
*m: do_calculeaza_discount
|
||||
*m: do_calculeaza_pretctva
|
||||
@@ -1155,7 +1157,7 @@ DEFINE CLASS frm_articol_factura AS _frmbase OF "_frm_base.vcx"
|
||||
BorderStyle = 1
|
||||
Caption = "Form"
|
||||
DoCreate = .T.
|
||||
Height = 450
|
||||
Height = 500
|
||||
larata = .T.
|
||||
lcuadaos = .T.
|
||||
lmodpretctva = .F.
|
||||
@@ -1284,6 +1286,16 @@ DEFINE CLASS frm_articol_factura AS _frmbase OF "_frm_base.vcx"
|
||||
_lbbase1.Top = 6
|
||||
*< END OBJECT: ClassLib="lb_tx.vcx" BaseClass="container" />
|
||||
|
||||
ADD OBJECT 'ck_pret_cu_tva' AS _checkbox WITH ;
|
||||
Alignment = 0, ;
|
||||
Caption = "Pret cu TVA inclus", ;
|
||||
ControlSource = "poArticol.preturi_cu_tva", ;
|
||||
Left = 6, ;
|
||||
Name = "ck_pret_cu_tva", ;
|
||||
TabIndex = 24, ;
|
||||
Top = 464
|
||||
*< END OBJECT: ClassLib="_baza.vcx" BaseClass="checkbox" />
|
||||
|
||||
ADD OBJECT 'clb_articol' AS clb_tx_simplu WITH ;
|
||||
Left = 6, ;
|
||||
Name = "clb_articol", ;
|
||||
@@ -1792,6 +1804,51 @@ DEFINE CLASS frm_articol_factura AS _frmbase OF "_frm_base.vcx"
|
||||
_lbbase1.Top = 6
|
||||
*< END OBJECT: ClassLib="lb_tx.vcx" BaseClass="container" />
|
||||
|
||||
PROCEDURE do_aplica_mod_pret
|
||||
Lparameters lnTip && 1 = sume in lei, 2 = sume in valuta
|
||||
If Inlist(poDate.tip,1,5,10,22,23,25,29,41) && documente pe baza de lista de preturi (1/5 factura lei si valuta, 10 factura fiscala in valuta, 22 aviz clienti, 23/25/41 transfer subunitati, 29 aviz clienti debitori): pretul e editabil oricum, pe restul doar daca e 0
|
||||
If poArticol.preturi_cu_tva = 0
|
||||
Thisform.lmodpretftva = .T.
|
||||
Thisform.clb_pretftva.do_activeaza(lnTip)
|
||||
Else
|
||||
Thisform.lmodpretctva = .T.
|
||||
Thisform.clb_pretctva.do_activeaza(lnTip)
|
||||
Endif
|
||||
Else
|
||||
If Type('Thisform.clb_procent_adaos') = 'O'
|
||||
Thisform.clb_procent_adaos.Visible = .F.
|
||||
Endif
|
||||
Thisform.lcuadaos = .F.
|
||||
If poArticol.preturi_cu_tva = 0 And ;
|
||||
((poArticol.pretftva = 0 And lnTip = 1) Or (poArticol.pretftva_val = 0 And lnTip = 2))
|
||||
Thisform.lmodpretftva = .T.
|
||||
Thisform.clb_pretftva.do_activeaza(lnTip)
|
||||
Else
|
||||
If poArticol.preturi_cu_tva = 1 And ;
|
||||
((poArticol.pretctva = 0 And lnTip = 1) Or (poArticol.pretctva_val = 0 And lnTip = 2))
|
||||
Thisform.lmodpretctva = .T.
|
||||
Thisform.clb_pretctva.do_activeaza(lnTip)
|
||||
Endif
|
||||
Endif
|
||||
Endif
|
||||
|
||||
If poArticol.preturi_cu_tva = 0
|
||||
Thisform.clb_discount_unitar.do_activeaza(lnTip)
|
||||
Thisform.clb_totalfdiscount.lb_explicatii.Caption = []
|
||||
Thisform.clb_totalcdiscount.lb_explicatii.Caption = []
|
||||
Thisform.clb_pret_diminuat.lb_explicatii.Caption = [(2) - (5)]
|
||||
Else
|
||||
Thisform.clb_discountctva.do_activeaza(lnTip)
|
||||
Thisform.clb_totalfdiscount.lb_explicatii.Caption = [(1) * (4)]
|
||||
Thisform.clb_totalcdiscount.lb_explicatii.Caption = [(1) * ( (4) - (7) )]
|
||||
With Thisform.clb_pret_diminuat
|
||||
.lb_explicatie.Caption = [Pret unitar diminuat cu TVA]
|
||||
.lb_explicatii.Caption = [(4) - (7)]
|
||||
Endwith
|
||||
Endif
|
||||
Thisform.ck_pret_cu_tva.Enabled = (Thisform.lmodpretftva Or Thisform.lmodpretctva)
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE do_calculeaza_adaos
|
||||
Lparameters tnValoare,tnTip
|
||||
If Thisform.lcuadaos
|
||||
@@ -2364,54 +2421,7 @@ DEFINE CLASS frm_articol_factura AS _frmbase OF "_frm_base.vcx"
|
||||
*!* *!* modificare v 2.0.46 ^
|
||||
*!* modificare v 2.0.74 ^
|
||||
|
||||
*!* modificare v 2.0.4
|
||||
*!* If Iif(Type('poArticol.modificabil')<>'U',poArticol.modificabil,0) = 1
|
||||
*!* modificare v 2.0.30 : am adaugat 41
|
||||
*!* modificare v 2.0.44 : am adaugat 42
|
||||
*!* If Inlist(poDate.tip,1,3,5,21,22,23,25,28,29,41,42)
|
||||
If Inlist(poDate.tip,1,5,10,22,23,25,29,41) && modificare v 2.0.56 : am adaugat 10
|
||||
*!* modificare v 2.0.4 ^
|
||||
If poArticol.preturi_cu_tva = 0
|
||||
Thisform.lmodpretftva = .T.
|
||||
Thisform.clb_pretftva.do_activeaza(lnTip)
|
||||
Else
|
||||
Thisform.lmodpretctva = .T.
|
||||
*!* modificare v 2.0.4
|
||||
*!* Thisform.RemoveObject('clb_procent_adaos')
|
||||
*!* thisform.lcuadaos = .F.
|
||||
*!* modificare v 2.0.4 ^
|
||||
Thisform.clb_pretctva.do_activeaza(lnTip)
|
||||
Endif
|
||||
Else
|
||||
Thisform.clb_procent_adaos.Visible = .F.
|
||||
Thisform.lcuadaos = .F.
|
||||
If poArticol.preturi_cu_tva = 0 And ;
|
||||
((poArticol.pretftva = 0 And lnTip = 1) Or (poArticol.pretftva_val = 0 And lnTip = 2))
|
||||
Thisform.lmodpretftva = .T.
|
||||
Thisform.clb_pretftva.do_activeaza(lnTip)
|
||||
Else
|
||||
If poArticol.preturi_cu_tva = 1 And ;
|
||||
((poArticol.pretctva = 0 And lnTip = 1) Or (poArticol.pretctva_val = 0 And lnTip = 2))
|
||||
Thisform.lmodpretctva = .T.
|
||||
Thisform.clb_pretctva.do_activeaza(lnTip)
|
||||
Endif
|
||||
Endif
|
||||
Endif
|
||||
|
||||
If poArticol.preturi_cu_tva = 0
|
||||
Thisform.clb_discount_unitar.do_activeaza(lnTip)
|
||||
Thisform.clb_totalfdiscount.lb_explicatii.Caption = []
|
||||
Thisform.clb_totalcdiscount.lb_explicatii.Caption = []
|
||||
Thisform.clb_pret_diminuat.lb_explicatii.Caption = [(2) - (5)]
|
||||
Else
|
||||
Thisform.clb_discountctva.do_activeaza(lnTip)
|
||||
Thisform.clb_totalfdiscount.lb_explicatii.Caption = [(1) * (4)]
|
||||
Thisform.clb_totalcdiscount.lb_explicatii.Caption = [(1) * ( (4) - (7) )]
|
||||
With Thisform.clb_pret_diminuat
|
||||
.lb_explicatie.Caption = [Pret unitar diminuat cu TVA]
|
||||
.lb_explicatii.Caption = [(4) - (7)]
|
||||
Endwith
|
||||
Endif
|
||||
Thisform.do_aplica_mod_pret(lnTip)
|
||||
|
||||
*!* modificare v 2.0.19
|
||||
*!* If (poDate.tip=2 And pnTipFacturare=3) Or INLIST(poDate.tip,4,23)
|
||||
@@ -2570,6 +2580,19 @@ DEFINE CLASS frm_articol_factura AS _frmbase OF "_frm_base.vcx"
|
||||
Thisform.UpdateExplicatieSaft()
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE ck_pret_cu_tva.InteractiveChange
|
||||
Local lnTip
|
||||
poArticol.preturi_cu_tva = This.Value
|
||||
lnTip = Iif(poArticol.tip_valuta = 0, 1, 2)
|
||||
If This.Value = 1
|
||||
Thisform.do_calculeaza_pretftva(Iif(lnTip = 1, poArticol.pretctva, poArticol.pretctva_val), lnTip)
|
||||
Else
|
||||
Thisform.do_calculeaza_pretctva(Iif(lnTip = 1, poArticol.pretftva, poArticol.pretftva_val), lnTip)
|
||||
Endif
|
||||
Thisform.do_aplica_mod_pret(lnTip)
|
||||
Thisform.do_calculeaza_totaluri()
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE clb_cantitate.Text_simplu1.InteractiveChange
|
||||
lcval=This.ControlSource
|
||||
&lcval=This.Value
|
||||
@@ -3146,7 +3169,7 @@ DEFINE CLASS frm_articol_gest_factura AS frm_articol_factura OF "ofacturare.vcx"
|
||||
*<PropValue>
|
||||
cgridsortlist = grd_gestiuni
|
||||
DoCreate = .T.
|
||||
Height = 510
|
||||
Height = 546
|
||||
lretur = .F.
|
||||
Name = "frm_articol_gest_factura"
|
||||
Width = 835
|
||||
@@ -3398,6 +3421,9 @@ DEFINE CLASS frm_articol_gest_factura AS frm_articol_factura OF "ofacturare.vcx"
|
||||
Cb_contract._cbbase1.Top = 3
|
||||
Cb_contract._cbbase1.Width = 274
|
||||
Cb_contract._lbbase1.Name = "_lbbase1"
|
||||
ck_pret_cu_tva.Left = 13
|
||||
ck_pret_cu_tva.Name = "ck_pret_cu_tva"
|
||||
ck_pret_cu_tva.Top = 510
|
||||
*</PropValue>
|
||||
|
||||
ADD OBJECT 'Cb_tx_articol' AS cb_tx_cautare WITH ;
|
||||
@@ -11048,6 +11074,7 @@ DEFINE CLASS frm_facturare_articole AS _frmbase OF "_frm_base.vcx"
|
||||
*< OBJECTDATA: ObjPath="grd_contracte.cNumar_contract.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="grd_contracte.cCodbare.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="grd_contracte.cCodbare.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="But_modifica1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="But_sterge1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="lb_total_mod" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="Gridextra1" UniqueID="" Timestamp="" />
|
||||
@@ -11162,6 +11189,16 @@ DEFINE CLASS frm_facturare_articole AS _frmbase OF "_frm_base.vcx"
|
||||
Gridsort1.Top = 36
|
||||
*</PropValue>
|
||||
|
||||
ADD OBJECT 'But_modifica1' AS but_modifica WITH ;
|
||||
Anchor = 9, ;
|
||||
caction = do_modifica, ;
|
||||
Left = 773, ;
|
||||
Name = "But_modifica1", ;
|
||||
TabIndex = 13, ;
|
||||
Top = 61, ;
|
||||
Visible = .T.
|
||||
*< END OBJECT: ClassLib="cmd_butoane.vcx" BaseClass="commandbutton" />
|
||||
|
||||
ADD OBJECT 'But_renunt1' AS but_renunt WITH ;
|
||||
Anchor = 8, ;
|
||||
Height = 27, ;
|
||||
@@ -13161,12 +13198,15 @@ DEFINE CLASS frm_facturare_articole AS _frmbase OF "_frm_base.vcx"
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE do_alege_stoc
|
||||
Lparameters tnIdArticol,tnCantitate,tcNumeArticol,tlImplicit,tnPret,tnDiscount,toGrid, tlRetur
|
||||
Lparameters tnIdArticol,tnCantitate,tcNumeArticol,tlImplicit,tnPret,tnDiscount,toGrid, tlRetur, tnIdTempExclus
|
||||
* llImplicit => vezi thisform.do_adauga
|
||||
* tnPret => doar pentru retururi : e pretul de vanzare fara TVA
|
||||
* toGrid => gridul din care vine articolul
|
||||
* tlRetur => factura normala cu articol retur (nu factura de retur tip 8,9). se comporta la fel ca factura de retur. se selecteaza din RUL, dar nu stiu factura din care fac retur
|
||||
|
||||
* tnIdTempExclus => id_temp-ul liniei modificate, exclus din cantitatea deja retinuta pe factura (0 la adaugare)
|
||||
If Type('tnIdTempExclus') <> 'N'
|
||||
tnIdTempExclus = 0
|
||||
Endif
|
||||
Private pnIdArticol
|
||||
Local llReturn,lofrmadarticol,lcSql, llFacturareFaraStoc
|
||||
llFactuareFaraStoc = .F.
|
||||
@@ -13232,7 +13272,7 @@ DEFINE CLASS frm_facturare_articole AS _frmbase OF "_frm_base.vcx"
|
||||
* Arat cantitatile din stoc - cantitatile deja pe factura curenta
|
||||
Select Iif(poDate.tip=41,-1,1)*Sum(cantitate) As cantitate,id_articol,id_gestiune,pret_achizitie,serie,lot,Cont, ;
|
||||
id_part_rez,id_lucrare_rez,pretv_orig,pretd,id_valuta_d ;
|
||||
FROM crsfactura Where id_articol = pnIdArticol ;
|
||||
FROM crsfactura Where id_articol = pnIdArticol And id_temp <> tnIdTempExclus ;
|
||||
GROUP By id_articol,id_gestiune,pret_achizitie,serie,lot,Cont,id_part_rez,id_lucrare_rez,pretv_orig,pretd,id_valuta_d ;
|
||||
INTO CURSOR crsFacturaArticoleTemp
|
||||
|
||||
@@ -13275,6 +13315,12 @@ DEFINE CLASS frm_facturare_articole AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
SELECT (m.lcCursor)
|
||||
Go Top
|
||||
If tnIdTempExclus > 0
|
||||
Locate For id_gestiune = poArticol.id_gestiune And Pret = poArticol.pret_achizitie And Cont = poArticol.Cont And Nvl(serie,'') = Nvl(poArticol.serie,'') And Nvl(lot,'') = Nvl(poArticol.lot,'') And Nvl(id_part_rez,0) = Nvl(poArticol.id_part_rez,0) And Nvl(id_lucrare_rez,0) = Nvl(poArticol.id_lucrare_rez,0) And pretv = poArticol.pretv_orig And pretd = poArticol.pretd And Nvl(id_valuta,0) = Nvl(poArticol.id_valuta_d,0)
|
||||
If !Found()
|
||||
Go Top
|
||||
Endif
|
||||
Endif
|
||||
Do Case
|
||||
Case Reccount(lcCursor) = 0
|
||||
amessagebox("Articolul "+Alltrim(tcNumeArticol)+" nu mai este pe stoc!",0+48,"Atentie")
|
||||
@@ -13697,6 +13743,176 @@ DEFINE CLASS frm_facturare_articole AS _frmbase OF "_frm_base.vcx"
|
||||
*!* modificare v 2.0.67 ^
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE do_modifica
|
||||
If Reccount('crsfactura')>0
|
||||
Private poArticol, pnProcentDiscountMem
|
||||
Local lnRecno, ofrmadarticol
|
||||
Select crsfactura
|
||||
lnRecno = Recno()
|
||||
Scatter Name poArticol MEMO
|
||||
|
||||
AddProperty(poArticol,'preturi_cu_tva',poArticol.cu_tva)
|
||||
AddProperty(poArticol,'discount_unitar',poArticol.discountftva)
|
||||
AddProperty(poArticol,'discount_unitar_ctva',poArticol.discountctva)
|
||||
AddProperty(poArticol,'pretftva_val',poArticol.vpretftva)
|
||||
AddProperty(poArticol,'pretctva_val',poArticol.vpretctva)
|
||||
AddProperty(poArticol,'discount_unitar_val',poArticol.vdiscountftva)
|
||||
AddProperty(poArticol,'discount_unitar_ctva_val',poArticol.vdiscountctva)
|
||||
Removeproperty(poArticol,'cu_tva')
|
||||
Removeproperty(poArticol,'discountftva')
|
||||
Removeproperty(poArticol,'discountctva')
|
||||
Removeproperty(poArticol,'vpretftva')
|
||||
Removeproperty(poArticol,'vpretctva')
|
||||
Removeproperty(poArticol,'vdiscountftva')
|
||||
Removeproperty(poArticol,'vdiscountctva')
|
||||
AddProperty(poArticol,'tva',poArticol.pretctva - poArticol.pretftva)
|
||||
AddProperty(poArticol,'tva_val',poArticol.pretctva_val - poArticol.pretftva_val)
|
||||
|
||||
pnProcentDiscountMem = 0
|
||||
If Nvl(gnMemProcDisc, 0) = 1
|
||||
pnProcentDiscountMem = Thisform.nproc_disc_mem
|
||||
Endif
|
||||
* plafonul de cantitate = stocul disponibil reconstituit din cursorul sursa; fara randul in cursor ramane cantitatea liniei
|
||||
Local lnCantitateMax, lcCursorStoc, lcAliasCrt, lnRecnoStoc, lnCantitateVeche, lnIdTempLinie, lnDeltaCantitate, lnTotalCantitate
|
||||
lnCantitateMax = poArticol.cantitate
|
||||
lcCursorStoc = Iif(poArticol.opt_facturare = 0, [crsarticole], [crsarticole1])
|
||||
If Used(lcCursorStoc)
|
||||
lcAliasCrt = Alias()
|
||||
Select (lcCursorStoc)
|
||||
lnRecnoStoc = Recno()
|
||||
Locate For id_c = poArticol.id_c
|
||||
If Found()
|
||||
Do Case
|
||||
Case (gnScadereStoc = 1 And poDate.tip = 23) Or Inlist(poDate.tip, 4, 21, 28, 42, 47) && adaugarea scade stocul; lista e cea validata la plafon (fara 3 si 25): 23 transfer subunitati, 4 din avize, 21/28/42/47 catre clienti
|
||||
lnCantitateMax = cantitate + poArticol.cantitate
|
||||
Case Inlist(poDate.tip, 8, 9, 24) && adaugarea creste stocul: 8/9 retur factura in lei si in valuta, 24 aviz de retur
|
||||
lnCantitateMax = cantitate - poArticol.cantitate
|
||||
Endcase
|
||||
Endif
|
||||
Try
|
||||
Go lnRecnoStoc
|
||||
Catch
|
||||
Go Top
|
||||
Endtry
|
||||
Select (lcAliasCrt)
|
||||
Endif
|
||||
|
||||
gnButon = 2
|
||||
lnCantitateVeche = poArticol.cantitate
|
||||
lnIdTempLinie = poArticol.id_temp
|
||||
Do Case
|
||||
Case (poArticol.gestionabil = 0 Or gnScadereStoc = 0 Or poDate.tip = 45) && 45 = ROARESTAURANT
|
||||
ofrmadarticol = Createobject("frm_articol_factura", lnCantitateMax, .F.)
|
||||
ofrmadarticol.Show(1)
|
||||
Release ofrmadarticol
|
||||
Otherwise
|
||||
Thisform.do_alege_stoc(poArticol.id_articol, lnCantitateMax, poArticol.denumire, .F., poArticol.pretftva, poArticol.discount_unitar, Thisform.grd_factura, .F., lnIdTempLinie)
|
||||
Endcase
|
||||
If gnButon = 1
|
||||
Select crsfactura
|
||||
Try
|
||||
Go lnRecno
|
||||
Catch
|
||||
Go Top
|
||||
Endtry
|
||||
If Used('crsartselectate')
|
||||
lnTotalCantitate = poArticol.cantitate
|
||||
Select crsartselectate
|
||||
Go Top
|
||||
poArticol.pret_achizitie = Pret
|
||||
poArticol.serie = Nvl(serie, [])
|
||||
poArticol.lot = Nvl(lot, [])
|
||||
poArticol.id_gestiune = id_gestiune
|
||||
poArticol.Cont = Alltrim(Cont)
|
||||
poArticol.cantitate = cantitate
|
||||
poArticol.pretv_orig = pretv
|
||||
poArticol.id_lucrare_rez = id_lucrare_rez
|
||||
poArticol.id_part_rez = id_part_rez
|
||||
poArticol.pretd = pretd
|
||||
poArticol.id_valuta_d = id_valuta
|
||||
Select crsfactura
|
||||
Endif
|
||||
Gather Name poArticol Fields Like pret_achizitie, denumire, cantitate, id_articol, Id_Pol, Cont, id_gestiune, Proc_Tvav, ;
|
||||
pretftva, valftva, valtva, valctva, valdiscountftva, valdiscounttva, valdiscountctva, Pretctva, ;
|
||||
valdiminuatftva, valdiminuattva, valdiminuatctva, ;
|
||||
vvalftva, vvaltva, vvalctva, vvaldiscountftva, vvaldiscounttva, vvaldiscountctva, ;
|
||||
vvaldiminuatftva, vvaldiminuattva, vvaldiminuatctva, id_c, lot, serie, explicatie, ;
|
||||
id_valuta, gestionabil, tip_valuta, id_jtva_coloana, taxcode, id_lucrare_rez, id_part_rez, pretv_orig, pretd, id_valuta_d, id_ctr, opt_facturare, nume_val MEMO
|
||||
Replace cu_tva With poArticol.preturi_cu_tva, ;
|
||||
discountftva With poArticol.discount_unitar, discountctva With poArticol.discount_unitar_ctva, ;
|
||||
vpretftva With Nvl(poArticol.pretftva_val,0), vpretctva With Nvl(poArticol.pretctva_val,0), ;
|
||||
vdiscountftva With Nvl(poArticol.discount_unitar_val,0), vdiscountctva With Nvl(poArticol.discount_unitar_ctva_val,0)
|
||||
If Used('crsartselectate')
|
||||
Select crsartselectate
|
||||
Skip
|
||||
Scan Rest
|
||||
poArticol.pret_achizitie = Pret
|
||||
poArticol.serie = Nvl(serie, [])
|
||||
poArticol.lot = Nvl(lot, [])
|
||||
poArticol.id_gestiune = id_gestiune
|
||||
poArticol.Cont = Alltrim(Cont)
|
||||
poArticol.cantitate = cantitate
|
||||
poArticol.pretv_orig = pretv
|
||||
poArticol.id_lucrare_rez = id_lucrare_rez
|
||||
poArticol.id_part_rez = id_part_rez
|
||||
poArticol.pretd = pretd
|
||||
poArticol.id_valuta_d = id_valuta
|
||||
Select crsfactura
|
||||
Append Blank
|
||||
Gather Name poArticol Fields Like pret_achizitie, denumire, cantitate, id_articol, Id_Pol, ;
|
||||
Cont, id_gestiune, Proc_Tvav, pretftva, Pretctva, ;
|
||||
id_c, lot, serie, explicatie, ;
|
||||
id_valuta, gestionabil, tip_valuta, id_jtva_coloana, taxcode, id_lucrare_rez, id_part_rez, pretv_orig, pretd, id_valuta_d, nume_val, id_ctr, opt_facturare MEMO
|
||||
Replace id_temp With Recno(), codmat With Nvl(poArticol.codmat, Space(50)), ;
|
||||
codbare With Nvl(poArticol.codbare, Space(50)), ;
|
||||
codmatf With Nvl(poArticol.codmatf, Space(50)), um With Nvl(poArticol.um, Space(50)), ;
|
||||
Curs With Nvl(poArticol.Curs, 0), multiplicator With Nvl(poArticol.multiplicator, 1), ;
|
||||
cu_tva With poArticol.preturi_cu_tva, ;
|
||||
vpretftva With Nvl(poArticol.pretftva_val, 0), vpretctva With Nvl(poArticol.pretctva_val, 0), ;
|
||||
discountftva With poArticol.discount_unitar, discountctva With poArticol.discount_unitar_ctva, ;
|
||||
vdiscountftva With Nvl(poArticol.discount_unitar_val, 0), ;
|
||||
vdiscountctva With Nvl(poArticol.discount_unitar_ctva_val, 0)
|
||||
poArticol = calculeaza_totaluri(poArticol)
|
||||
Gather Name poArticol Fields Like valftva, valtva, valctva, ;
|
||||
valdiscountftva, valdiscounttva, valdiscountctva, ;
|
||||
valdiminuatftva, valdiminuattva, valdiminuatctva, ;
|
||||
vvalftva, vvaltva, vvalctva, ;
|
||||
vvaldiscountftva, vvaldiscounttva, vvaldiscountctva, ;
|
||||
vvaldiminuatftva, vvaldiminuattva, vvaldiminuatctva MEMO
|
||||
Endscan
|
||||
Use In crsartselectate
|
||||
poArticol.cantitate = lnTotalCantitate
|
||||
Select crsfactura
|
||||
Endif
|
||||
lnDeltaCantitate = poArticol.cantitate - lnCantitateVeche
|
||||
If lnDeltaCantitate <> 0 And Used(lcCursorStoc)
|
||||
lcAliasCrt = Alias()
|
||||
Select (lcCursorStoc)
|
||||
lnRecnoStoc = Recno()
|
||||
Do Case
|
||||
Case (gnScadereStoc = 1 And poDate.tip = 23) Or Inlist(poDate.tip, 4, 21, 28, 42, 47)
|
||||
Replace cantitate With cantitate - lnDeltaCantitate For id_c = poArticol.id_c
|
||||
Case Inlist(poDate.tip, 8, 9, 24)
|
||||
Replace cantitate With cantitate + lnDeltaCantitate For id_c = poArticol.id_c
|
||||
Endcase
|
||||
Try
|
||||
Go lnRecnoStoc
|
||||
Catch
|
||||
Go Top
|
||||
Endtry
|
||||
Select (lcAliasCrt)
|
||||
Endif
|
||||
If Nvl(gnMemProcDisc, 0) = 1
|
||||
Thisform.nproc_disc_mem = pnProcentDiscountMem
|
||||
Endif
|
||||
Thisform.do_calculeaza_totaluri()
|
||||
Thisform.grd_factura.Refresh()
|
||||
Thisform.grd_factura.SetFocus()
|
||||
Endif
|
||||
Release poArticol, pnProcentDiscountMem
|
||||
Endif
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE do_renunt
|
||||
*!* modificare 19.01.2007
|
||||
DODEFAULT()
|
||||
@@ -13854,8 +14070,8 @@ DEFINE CLASS frm_facturare_articole AS _frmbase OF "_frm_base.vcx"
|
||||
Alltrim(Str(poArt.id_articol)) + [,] + ;
|
||||
['] + OracleSpecialCharacters(Alltrim(Nvl(poArt.serie,[]))) + [',] + ;
|
||||
['] + OracleSpecialCharacters(Alltrim(Nvl(poArt.explicatie,''))) + [',] + Nvl(Alltrim(Str(poArt.id_pol)),[NULL]) + [,] + ;
|
||||
Nvl(Alltrim(Str(poArt.id_gestiune)),[NULL]) + [,] + Alltrim(Str(poArt.pret_achizitie,18,gnPPret)) + [,] + ;
|
||||
Alltrim(Str(poArt.pretd,18,gnPPretval)) + [,] + ;
|
||||
Nvl(Alltrim(Str(poArt.id_gestiune)),[NULL]) + [,] + Alltrim(Str(poArt.pret_achizitie,18,Max(gnPPret,4))) + [,] + ;
|
||||
Alltrim(Str(poArt.pretd,18,Max(gnPPretval,4))) + [,] + ;
|
||||
Iif(Isnull(poArt.id_valuta_d),[NULL],Alltrim(Str(poArt.id_valuta_d))) + [,] + ;
|
||||
IIF(poArt.cu_tva=0,;
|
||||
IIF(poArt.tip_valuta = 0,Alltrim(Str(poArt.pretftva,18,gnPPretV)),Alltrim(Str(poArt.vpretftva,18,gnPVal))),;
|
||||
@@ -13868,7 +14084,7 @@ DEFINE CLASS frm_facturare_articole AS _frmbase OF "_frm_base.vcx"
|
||||
['] + Alltrim(Nvl(poArt.Cont,'')) + [',] + Alltrim(Str(poArt.Curs,18,6)) + [,] + ;
|
||||
ALLTRIM(STR(poArt.multiplicator,10)) + [,] + Alltrim(Str(poArt.id_jtva_coloana)) + [,] + ;
|
||||
Nvl(Alltrim(Str(poArt.id_part_rez)),[NULL]) + [,] + Nvl(Alltrim(Str(poArt.id_lucrare_rez)),[NULL]) + [,] + ;
|
||||
Alltrim(Str(poArt.pretv_orig,18,gnPPretV)) + [,] + ;
|
||||
Alltrim(Str(poArt.pretv_orig,18,Max(gnPPretV,4))) + [,] + ;
|
||||
Nvl(Alltrim(Str(poArt.id_set_fact)),[NULL]) + [,] + NVL(ALLTRIM(STR(poArt.id_ctr)),[NULL]) + [,] + Alltrim(Str(gnIdUtil)) + [,] + ;
|
||||
NVL(ALLTRIM(STR(poArt.taxcode)),[NULL]) + ;
|
||||
[,'] + OracleSpecialCharacters(Alltrim(Nvl(poArt.lot,[]))) + ['] + ;
|
||||
@@ -14006,7 +14222,6 @@ DEFINE CLASS frm_facturare_articole AS _frmbase OF "_frm_base.vcx"
|
||||
pnParametruAditional = 0
|
||||
llReturn = .T.
|
||||
lcListaIncasare = ''
|
||||
SET STEP ON
|
||||
llEproforma = (poDate.eProforma = 1)
|
||||
|
||||
If Inlist(poDate.ntip_incasare, 11, 2, 3) && 11 = CHITANTA, 2 = BON FISCAL, 3 = POS/Card
|
||||
@@ -15513,6 +15728,10 @@ DEFINE CLASS frm_facturare_articole AS _frmbase OF "_frm_base.vcx"
|
||||
*Nu sterge
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE grd_factura.DblClick
|
||||
Thisform.do_modifica()
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE grd_factura.Init
|
||||
*Nu sterge
|
||||
ENDPROC
|
||||
@@ -17886,8 +18105,8 @@ DEFINE CLASS frm_facturare_articole2 AS _frmbase OF "_frm_base.vcx"
|
||||
Alltrim(Str(poArt.id_articol)) + [,] + ;
|
||||
['] + OracleSpecialCharacters(Alltrim(Nvl(poArt.serie,[]))) + [',] + ;
|
||||
['] + OracleSpecialCharacters(Alltrim(Nvl(poArt.explicatie,''))) + [',] + Nvl(Alltrim(Str(poArt.id_pol)),[NULL]) + [,] + ;
|
||||
Nvl(Alltrim(Str(poArt.id_gestiune)),[NULL]) + [,] + Alltrim(Str(poArt.pret_achizitie,18,gnPPret)) + [,] + ;
|
||||
Alltrim(Str(poArt.pretd,18,gnPPretval)) + [,] + ;
|
||||
Nvl(Alltrim(Str(poArt.id_gestiune)),[NULL]) + [,] + Alltrim(Str(poArt.pret_achizitie,18,Max(gnPPret,4))) + [,] + ;
|
||||
Alltrim(Str(poArt.pretd,18,Max(gnPPretval,4))) + [,] + ;
|
||||
Iif(Isnull(poArt.id_valuta_d),[NULL],Alltrim(Str(poArt.id_valuta_d))) + [,] + ;
|
||||
IIF(poArt.cu_tva=0,;
|
||||
IIF(poArt.tip_valuta = 0,Alltrim(Str(poArt.pretftva,18,gnPPretV)),Alltrim(Str(poArt.vpretftva,18,gnPVal))),;
|
||||
@@ -17900,7 +18119,7 @@ DEFINE CLASS frm_facturare_articole2 AS _frmbase OF "_frm_base.vcx"
|
||||
['] + Alltrim(Nvl(poArt.Cont,'')) + [',] + Alltrim(Str(poArt.Curs,18,6)) + [,] + ;
|
||||
ALLTRIM(STR(poArt.multiplicator,10)) + [,] + Alltrim(Str(poArt.id_jtva_coloana)) + [,] + ;
|
||||
Nvl(Alltrim(Str(poArt.id_part_rez)),[NULL]) + [,] + Nvl(Alltrim(Str(poArt.id_lucrare_rez)),[NULL]) + [,] + ;
|
||||
Alltrim(Str(poArt.pretv_orig,18,gnPPretV)) + [,] + ;
|
||||
Alltrim(Str(poArt.pretv_orig,18,Max(gnPPretV,4))) + [,] + ;
|
||||
Nvl(Alltrim(Str(poArt.id_set_fact)),[NULL]) + [,] + NVL(ALLTRIM(STR(poArt.id_ctr)),[NULL]) + [,] + Alltrim(Str(gnIdUtil)) + [);]
|
||||
*!* v 2.0.13 ^
|
||||
*!* modificare v 2.0.67
|
||||
|
||||
@@ -1336,6 +1336,7 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
|
||||
*< OBJECTDATA: ObjPath="But_verifica1" UniqueID="" Timestamp="" />
|
||||
|
||||
*<DefinedPropArrayMethod>
|
||||
*m: do_editare_factura
|
||||
*m: do_listare_cc
|
||||
*m: do_listare_centr
|
||||
*m: do_listare_document
|
||||
@@ -3711,6 +3712,165 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
|
||||
This.do_cauta()
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE do_editare_factura
|
||||
If !This.lactiv3
|
||||
Return
|
||||
Endif
|
||||
|
||||
If Reccount('crsfacturi') = 0
|
||||
amessagebox("Nu exista inregistrari pentru editare!",0+48,"Atentie")
|
||||
Return
|
||||
Endif
|
||||
|
||||
If glLunaInchisa
|
||||
Return
|
||||
Endif
|
||||
|
||||
Local lnSters, llEProforma, lnIdSet, lnIdFactD, lnSucces, Omodif, llGasitRand
|
||||
Private pnAn, pnLuna, lnCod, lnIdFact, lnIdVanzare
|
||||
Store 0 To pnAn, pnLuna, lnCod, lnIdFact, lnIdSet, lnIdFactD, lnIdVanzare
|
||||
|
||||
Select crsfacturi
|
||||
lnIdVanzare = id_vanzare
|
||||
lnCod = cod
|
||||
pnAn = Year(data_act)
|
||||
pnLuna = Month(data_act)
|
||||
lnSters = sters
|
||||
lnIdFact = id_fact
|
||||
llEProforma = (eproforma = 1)
|
||||
|
||||
If lnSters = 1
|
||||
amessagebox("Acest document este deja sters!",0+48,"Atentie")
|
||||
Return
|
||||
Endif
|
||||
|
||||
If llEProforma
|
||||
amessagebox("Proformele nu pot fi editate pe aceasta cale!",0+48,"Atentie")
|
||||
Return
|
||||
Endif
|
||||
|
||||
If (pnAn * 12) + pnLuna <> (gnAn * 12) + gnLuna
|
||||
amessagebox('Nu puteti edita decat inregistrari din luna curenta!',0,'Atentie!')
|
||||
Return
|
||||
Endif
|
||||
|
||||
*** verificare restrictie editare documente cu referinte (incasari/plati)
|
||||
If ReferinteDocumenteNota(pnAn, pnLuna, lnCod) && odocumente.prg
|
||||
amessagebox("Documentul are referinte (incasari/plati). Nu poate fi editat.", 0+48,"Editare")
|
||||
Return
|
||||
Endif
|
||||
|
||||
*** verificare restrictie editare facturi trimise in eFactura
|
||||
If EsteInEFactura(lnIdFact) && ofacturare_editare.prg
|
||||
amessagebox("Documentul a fost trimis in eFactura. Nu poate fi editat.", 0+48,"Editare")
|
||||
Return
|
||||
Endif
|
||||
|
||||
If IncarcaCursoareModificareNota(lnCod, pnAn, pnLuna, .F.) && ofacturare_editare.prg
|
||||
If Reccount('actactan') = 0
|
||||
amessagebox("Nu exista nota contabila pentru aceasta factura.",0+48,"Atentie")
|
||||
Else
|
||||
Select actactan
|
||||
llGasitRand = .F.
|
||||
If lnIdFact > 0
|
||||
Locate For Nvl(id_fact, 0) = lnIdFact
|
||||
llGasitRand = Found()
|
||||
Endif
|
||||
If !llGasitRand
|
||||
*** rezerva: nota nu contine id_fact-ul din vanzari (avize, transferuri, documente vechi)
|
||||
Go Top
|
||||
lnIdFact = id_fact
|
||||
Endif
|
||||
lnIdSet = id_set
|
||||
lnIdFactD = id_factd
|
||||
|
||||
Select a.*, Iif(Nvl(id_jtva_coloana,0)=0,0,1) As cu_Tva From tact a Into Cursor tact Readwrite
|
||||
|
||||
update_jtva_coloane("", "crsJtvaTemp", 0)
|
||||
|
||||
*!* articolele se incarca ACUM, inainte de Createobject - grid-ul din pagina 3
|
||||
*!* se leaga o singura data, la construire, pe cursorul deja plin
|
||||
IncarcaArticoleFactura(m.lnIdVanzare, 'crsArticoleFactura')
|
||||
|
||||
Select tact
|
||||
Omodif = Createobject([frm_modific2024], lnIdSet)
|
||||
Omodif.Show()
|
||||
|
||||
If buton = 1
|
||||
If Thisform.do_deschide_tranzactie()
|
||||
Select actactan
|
||||
lnSucces = OSCRIE_IN_FISIERE(2,.T.,.T.)
|
||||
If lnSucces > 0
|
||||
If Used('actactan')
|
||||
Use In actactan
|
||||
Endif
|
||||
Select tact
|
||||
Replace id_jtva_coloana With Null, proc_tva With 0 For cu_Tva = 0
|
||||
Select * From tact Into Cursor actactan Readwrite
|
||||
Replace All id_util With gnIdUtil, sters With 0
|
||||
If Used('rul_temp')
|
||||
Use In rul_temp
|
||||
Endif
|
||||
Select * From trul Into Cursor RUL_TEMP Readwrite
|
||||
Replace All id_util With gnIdUtil, sters With 0
|
||||
If Used('rul_temp_obinv')
|
||||
Use In rul_temp_obinv
|
||||
Endif
|
||||
Select * From trul_obinv Into Cursor RUL_TEMP_OBINV Readwrite
|
||||
Replace All id_util With gnIdUtil, sters With 0
|
||||
lnSucces = OSCRIE_IN_FISIERE(0,.T.,.T.)
|
||||
Endif
|
||||
If lnSucces > 0
|
||||
lcSql = [begin pack_contafin.finalizeaza_modificare_nota(?pnLuna,?pnAn,Null,] + Alltrim(Str(lnIdSet)) + [,] + ;
|
||||
Alltrim(Str(lnCod)) + [,] + Alltrim(Str(lnIdFact)) + [,] + Alltrim(Str(lnIdFactD)) + [,?gnIdUtil); end;]
|
||||
lnSucces = Iif(goExecutor.oExecuta(lcSql),1,-1)
|
||||
Endif
|
||||
If lnSucces > 0 And "OFACTURARE_EDITARE" $ Upper(Set("Procedure")) And Used('tvanz') And Reccount('tvanz') = 1
|
||||
lnSucces = Iif(ScrieArticoleFacturaEditate(tvanz.id_vanzare), 1, -1)
|
||||
Endif
|
||||
If Thisform.do_inchide_tranzactie(Iif(lnSucces<0,2,1))
|
||||
If lnSucces > 0
|
||||
Thisform.do_cauta()
|
||||
Endif
|
||||
Endif
|
||||
Endif
|
||||
Endif
|
||||
Endif
|
||||
|
||||
If Used('actactan')
|
||||
Use In actactan
|
||||
Endif
|
||||
If Used('tact')
|
||||
Use In tact
|
||||
Endif
|
||||
If Used('rul_temp')
|
||||
Use In rul_temp
|
||||
Endif
|
||||
If Used('trul')
|
||||
Use In trul
|
||||
Endif
|
||||
If Used('rul_temp_obinv')
|
||||
Use In rul_temp_obinv
|
||||
Endif
|
||||
If Used('trul_obinv')
|
||||
Use In trul_obinv
|
||||
Endif
|
||||
If Used('crsJtvaTemp')
|
||||
Use In crsJtvaTemp
|
||||
Endif
|
||||
If Used('crsArticoleFactura')
|
||||
Use In crsArticoleFactura
|
||||
Endif
|
||||
Endif
|
||||
|
||||
Select crsfacturi
|
||||
Locate For id_vanzare = lnIdVanzare
|
||||
If !Found()
|
||||
Go Top
|
||||
Endif
|
||||
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE do_listare
|
||||
*!* 26.11.2019
|
||||
*!* marius.mutu
|
||||
@@ -4333,7 +4493,6 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
Select crsdetalii
|
||||
Calculate Max(proc_tvav) To lnProcTvav
|
||||
SET STEP ON
|
||||
creeaza_facturacrs([crsfactura])
|
||||
|
||||
prelucreaza_facturacrs([crsdetalii], [crsfactura], lnProcTvav, lnDiscount, lnDiscountVal)
|
||||
@@ -4382,7 +4541,6 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
|
||||
PROCEDURE do_modifica
|
||||
Local ofrmmodificare As "frm_modifica_factura"
|
||||
Local lcSql, lnSucces
|
||||
SET STEP ON
|
||||
PRIVATE poRec, pneFactura
|
||||
If Reccount('crsfacturi') > 0
|
||||
Local lnRecno, lnNrInreg, lnNrInregMod
|
||||
@@ -4764,7 +4922,18 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
Do verificare_parteneri With m.lcXMLParteneri, m.llValidare, m.llMFIN, m.llVerificarePlatitorTVA, m.llAutoVerificare, m.llDontCloseCursor, m.llExperimental, m.llServiciuWebANAF
|
||||
|
||||
USE IN (SELECT('crsCoduriFiscale'))
|
||||
USE IN (SELECT('crsCoduriFiscale'))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE inainte_de_do_modifica
|
||||
Local lnOptiune
|
||||
lnOptiune = xmenu('Modificare \<date factura;Editare \<factura (note, rulaje, articole)')
|
||||
Do Case
|
||||
Case lnOptiune = 1
|
||||
This.do_modifica()
|
||||
Case lnOptiune = 2
|
||||
This.do_editare_factura()
|
||||
Endcase
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE Init
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@ DEFINE CLASS actualizare_curs_bnr AS _custom OF "_baza.vcx"
|
||||
|
||||
*<PropValue>
|
||||
ccursor = ccrsbnr
|
||||
clink = https://www.bnr.ro/nbrfxrates.xml
|
||||
clink = https://curs.bnr.ro/nbrfxrates.xml
|
||||
ctempfile = C:\temp\temp.xml
|
||||
ddata = {}
|
||||
Height = 17
|
||||
|
||||
@@ -1596,6 +1596,8 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cInactiv.Check1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.Column26.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.Column26.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.Column27.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.Column27.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="But_verifica1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="Gridextra1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="chkMFIN" UniqueID="" Timestamp="" />
|
||||
@@ -1658,7 +1660,7 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
ADD OBJECT '_grdbase1' AS _grdbase WITH ;
|
||||
Anchor = 15, ;
|
||||
ColumnCount = 26, ;
|
||||
ColumnCount = 27, ;
|
||||
DeleteMark = .F., ;
|
||||
HeaderHeight = 32, ;
|
||||
Height = 283, ;
|
||||
@@ -1835,7 +1837,13 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
Column26.DynamicBackColor = "RGB(255,202,228)", ;
|
||||
Column26.Name = "Column26", ;
|
||||
Column26.ReadOnly = .T., ;
|
||||
Column26.Width = 150
|
||||
Column26.Width = 150, ;
|
||||
Column27.ColumnOrder = 27, ;
|
||||
Column27.ControlSource = "IIF(EMPTY(NVL(sursa,'')),'',IIF(ALLTRIM(sursa)=='ANAF','ANAF','CACHE '+DTOC(NVL(data_sursa,DATE()))+IIF(ALLTRIM(sursa)=='CACHE_INDISP',' (ANAF indisponibil)','')))", ;
|
||||
Column27.Name = "Column27", ;
|
||||
Column27.ReadOnly = .T., ;
|
||||
Column27.Visible = .T., ;
|
||||
Column27.Width = 230
|
||||
*< END OBJECT: ClassLib="_grd_base.vcx" BaseClass="grid" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cInactiv.Check1' AS checkbox WITH ;
|
||||
@@ -2011,7 +2019,7 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
ADD OBJECT '_grdbase1.Column16.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Data TVA MFIN", ;
|
||||
Caption = "Data verificata", ;
|
||||
Name = "Header1", ;
|
||||
WordWrap = .T.
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
@@ -2037,7 +2045,7 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
ADD OBJECT '_grdbase1.Column17.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Platitor TVA MFIN", ;
|
||||
Caption = "Platitor TVA ANAF", ;
|
||||
Name = "Header1", ;
|
||||
WordWrap = .T.
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
@@ -2170,6 +2178,22 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
SelectedBackColor = 100,185,255
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.Column27.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Provenienta", ;
|
||||
Name = "Header1"
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.Column27.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1", ;
|
||||
ReadOnly = .T., ;
|
||||
SelectedBackColor = 100,185,255
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.Column3.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "CIF/CNP", ;
|
||||
@@ -2215,7 +2239,7 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
ADD OBJECT '_grdbase1.Column5.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Firma MFIN", ;
|
||||
Caption = "Firma ANAF", ;
|
||||
Name = "Header1"
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
@@ -2695,7 +2719,6 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
lcConditieSuplimentara = Iif(m.llLiniaCurenta, "recno() >= " + Alltrim(Str(m.lnRecord)), ".T.")
|
||||
If m.llServiciuWebANAF
|
||||
SET STEP ON
|
||||
&& verificare serviciu web ANAF
|
||||
SELECT distinct cod_fiscal, IIF(!EMPTY(NVL(data, {})), data, DATE(m.gnAn, m.gnLuna, 1)) as data ;
|
||||
FROM crsVerificareParteneri ;
|
||||
@@ -2704,6 +2727,10 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
loVerificareANAF = CREATEOBJECT("VerificareANAF") && validare.prg
|
||||
|
||||
SELECT crsVerificareParteneri
|
||||
REPLACE ALL cod_fiscalfro WITH ALLTRIM(Strtran(cod_fiscal, loVerificare.GetCodTara(cod_fiscal),''))
|
||||
INDEX ON cod_fiscalfro TAG cfro
|
||||
|
||||
SELECT distinct data FROM cListaCIFTempX INTO CURSOR cListaCIFTempData
|
||||
SELECT cListaCIFTempData
|
||||
SCAN
|
||||
@@ -2718,16 +2745,29 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
SCAN
|
||||
SCATTER NAME loRec
|
||||
WITH loRec
|
||||
lcCheieCauta = PADR(ALLTRIM(STR(.cui)), 30)
|
||||
SELECT crsVerificareParteneri
|
||||
LOCATE FOR ALLTRIM(Strtran(cod_fiscal, loVerificare.GetCodTara(cod_fiscal),'')) = ALLTRIM(STR(.cui)) AND (EMPTY(NVL(data, {})) OR data = m.ldData)
|
||||
IF FOUND()
|
||||
llGasit = .F.
|
||||
IF SEEK(m.lcCheieCauta, 'crsVerificareParteneri', 'cfro')
|
||||
llGasit = .T.
|
||||
DO WHILE !(EMPTY(NVL(data, {})) OR data = m.ldData)
|
||||
SKIP
|
||||
IF EOF() OR cod_fiscalfro <> m.lcCheieCauta
|
||||
llGasit = .F.
|
||||
EXIT
|
||||
ENDIF
|
||||
ENDDO
|
||||
ENDIF
|
||||
IF llGasit
|
||||
Replace firma With .denumire, adresa With .adresa, datatvamfin With TRANSFORM(.data), platitortvamfin With .tva, stare With .mesaj, cod WITH ALLTRIM(STR(.cui)), ;
|
||||
tvaincasare WITH .tvaincasare, splittva WITH .splittva, inactiv WITH .inactiv
|
||||
ENDIF
|
||||
tvaincasare WITH .tvaincasare, splittva WITH .splittva, inactiv WITH .inactiv, ;
|
||||
sursa WITH NVL(.sursa, 'ANAF'), data_sursa WITH .data_sursa
|
||||
ENDIF
|
||||
ENDWITH
|
||||
ENDSCAN && (m.lcCursorVerificareANAF)
|
||||
ENDIF
|
||||
ENDSCAN && cListaCIFTempData
|
||||
SET ORDER TO 0 IN crsVerificareParteneri
|
||||
USE IN (SELECT('cListaCIFTempData'))
|
||||
USE IN (SELECT('cListaCIFTempX'))
|
||||
USE IN (SELECT('cListaCIFTemp'))
|
||||
@@ -2887,6 +2927,20 @@ DEFINE CLASS frm_verificare_parteneri AS _frmbase OF "_frm_base.vcx"
|
||||
this._grDBASE1.HeaderHeight = 32
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE Load
|
||||
*** campurile de provenienta (cache/ANAF) trebuie sa existe INAINTE ca grid-ul sa se construiasca (Load ruleaza inaintea obiectelor din forma);
|
||||
*** ALTER TABLE nu functioneaza pe acest cursor (are campuri peste 10 caractere, ex. platitortvamfin) - se rematerializeaza cu SELECT
|
||||
LOCAL lcAliasTmp
|
||||
IF TYPE('crsVerificareParteneri.sursa') = 'U'
|
||||
lcAliasTmp = 'crsVPTmp' + Sys(2015)
|
||||
SELECT *, SPACE(20) AS sursa, {} AS data_sursa FROM crsVerificareParteneri INTO CURSOR (lcAliasTmp) READWRITE
|
||||
USE IN (SELECT('crsVerificareParteneri'))
|
||||
SELECT * FROM (lcAliasTmp) INTO CURSOR crsVerificareParteneri READWRITE
|
||||
USE IN (SELECT(lcAliasTmp))
|
||||
ENDIF
|
||||
DODEFAULT()
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE meniu_dblclick
|
||||
*** Verificare cod fiscal de pe inregistrarea curenta
|
||||
Local loDate As "empty"
|
||||
@@ -3009,6 +3063,31 @@ DEFINE CLASS frm_verificare_parteneri_istoric AS _frmbase OF "_frm_base.vcx"
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataOraV.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cUtilV.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cUtilV.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataOravAnaf.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataOravAnaf.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cTvaIncasare.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cTvaIncasare.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cTvaIncasare._checkbox1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cSplitTva.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cSplitTva.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cSplitTva._checkbox1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cInactiv.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cInactiv.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cInactiv._checkbox1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataInceputScpTva.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataInceputScpTva.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataSfarsitScpTva.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataSfarsitScpTva.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataAnulImpScpTva.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataAnulImpScpTva.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataInceputTvaInc.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataInceputTvaInc.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataSfarsitTvaInc.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataSfarsitTvaInc.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataInactivare.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataInactivare.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataReactivare.Header1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="_grdbase1.cDataReactivare.Text1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="Gridextra1" UniqueID="" Timestamp="" />
|
||||
*< OBJECTDATA: ObjPath="lblInfo" UniqueID="" Timestamp="" />
|
||||
|
||||
@@ -3058,7 +3137,7 @@ DEFINE CLASS frm_verificare_parteneri_istoric AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
ADD OBJECT '_grdbase1' AS _grdbase WITH ;
|
||||
Anchor = 15, ;
|
||||
ColumnCount = 16, ;
|
||||
ColumnCount = 27, ;
|
||||
DeleteMark = .F., ;
|
||||
HeaderHeight = 32, ;
|
||||
Height = 190, ;
|
||||
@@ -3103,19 +3182,19 @@ DEFINE CLASS frm_verificare_parteneri_istoric AS _frmbase OF "_frm_base.vcx"
|
||||
Column6.ControlSource = "codpostal", ;
|
||||
Column6.Name = "cCodPostal", ;
|
||||
Column6.ReadOnly = .T., ;
|
||||
Column6.Visible = .T., ;
|
||||
Column6.Visible = .F., ;
|
||||
Column6.Width = 75, ;
|
||||
Column7.ColumnOrder = 11, ;
|
||||
Column7.ControlSource = "telefon", ;
|
||||
Column7.Name = "cTelefon", ;
|
||||
Column7.ReadOnly = .T., ;
|
||||
Column7.Visible = .T., ;
|
||||
Column7.Visible = .F., ;
|
||||
Column7.Width = 75, ;
|
||||
Column8.ColumnOrder = 12, ;
|
||||
Column8.ControlSource = "fax", ;
|
||||
Column8.Name = "cFax", ;
|
||||
Column8.ReadOnly = .T., ;
|
||||
Column8.Visible = .T., ;
|
||||
Column8.Visible = .F., ;
|
||||
Column8.Width = 75, ;
|
||||
Column9.ColumnOrder = 6, ;
|
||||
Column9.ControlSource = "platitortvavies", ;
|
||||
@@ -3123,18 +3202,20 @@ DEFINE CLASS frm_verificare_parteneri_istoric AS _frmbase OF "_frm_base.vcx"
|
||||
Column9.Name = "cPlatitorTVAVies", ;
|
||||
Column9.ReadOnly = .T., ;
|
||||
Column9.Sparse = .F., ;
|
||||
Column9.Visible = .T., ;
|
||||
Column9.Visible = .F., ;
|
||||
Column9.Width = 54, ;
|
||||
Column10.ColumnOrder = 5, ;
|
||||
Column10.ControlSource = "datatvamfin", ;
|
||||
Column10.Name = "cDataTVAMfin", ;
|
||||
Column10.ReadOnly = .T., ;
|
||||
Column10.Visible = .F., ;
|
||||
Column11.ColumnOrder = 4, ;
|
||||
Column11.ControlSource = "platitortvamfin", ;
|
||||
Column11.CurrentControl = "_checkbox1", ;
|
||||
Column11.Name = "cPlatitorTVAMfin", ;
|
||||
Column11.ReadOnly = .T., ;
|
||||
Column11.Sparse = .F., ;
|
||||
Column11.Visible = .F., ;
|
||||
Column11.Width = 51, ;
|
||||
Column12.ColumnOrder = 3, ;
|
||||
Column12.ControlSource = "stare", ;
|
||||
@@ -3154,7 +3235,57 @@ DEFINE CLASS frm_verificare_parteneri_istoric AS _frmbase OF "_frm_base.vcx"
|
||||
Column16.ControlSource = "utilv", ;
|
||||
Column16.Name = "cUtilV", ;
|
||||
Column16.ReadOnly = .T., ;
|
||||
Column16.Width = 114
|
||||
Column16.Width = 114, ;
|
||||
Column17.ControlSource = "dataorav_anaf", ;
|
||||
Column17.Name = "cDataOravAnaf", ;
|
||||
Column17.ReadOnly = .T., ;
|
||||
Column17.Width = 85, ;
|
||||
Column18.ControlSource = "tvaincasare", ;
|
||||
Column18.CurrentControl = "_checkbox1", ;
|
||||
Column18.Name = "cTvaIncasare", ;
|
||||
Column18.ReadOnly = .T., ;
|
||||
Column18.Sparse = .F., ;
|
||||
Column18.Width = 54, ;
|
||||
Column19.ControlSource = "splittva", ;
|
||||
Column19.CurrentControl = "_checkbox1", ;
|
||||
Column19.Name = "cSplitTva", ;
|
||||
Column19.ReadOnly = .T., ;
|
||||
Column19.Sparse = .F., ;
|
||||
Column19.Width = 54, ;
|
||||
Column20.ControlSource = "inactiv", ;
|
||||
Column20.CurrentControl = "_checkbox1", ;
|
||||
Column20.Name = "cInactiv", ;
|
||||
Column20.ReadOnly = .T., ;
|
||||
Column20.Sparse = .F., ;
|
||||
Column20.Width = 54, ;
|
||||
Column21.ControlSource = "data_inceput_scptva", ;
|
||||
Column21.Name = "cDataInceputScpTva", ;
|
||||
Column21.ReadOnly = .T., ;
|
||||
Column21.Width = 85, ;
|
||||
Column22.ControlSource = "data_sfarsit_scptva", ;
|
||||
Column22.Name = "cDataSfarsitScpTva", ;
|
||||
Column22.ReadOnly = .T., ;
|
||||
Column22.Width = 85, ;
|
||||
Column23.ControlSource = "data_anul_imp_scptva", ;
|
||||
Column23.Name = "cDataAnulImpScpTva", ;
|
||||
Column23.ReadOnly = .T., ;
|
||||
Column23.Width = 85, ;
|
||||
Column24.ControlSource = "data_inceput_tvainc", ;
|
||||
Column24.Name = "cDataInceputTvaInc", ;
|
||||
Column24.ReadOnly = .T., ;
|
||||
Column24.Width = 85, ;
|
||||
Column25.ControlSource = "data_sfarsit_tvainc", ;
|
||||
Column25.Name = "cDataSfarsitTvaInc", ;
|
||||
Column25.ReadOnly = .T., ;
|
||||
Column25.Width = 85, ;
|
||||
Column26.ControlSource = "data_inactivare", ;
|
||||
Column26.Name = "cDataInactivare", ;
|
||||
Column26.ReadOnly = .T., ;
|
||||
Column26.Width = 85, ;
|
||||
Column27.ControlSource = "data_reactivare", ;
|
||||
Column27.Name = "cDataReactivare", ;
|
||||
Column27.ReadOnly = .T., ;
|
||||
Column27.Width = 85
|
||||
*< END OBJECT: ClassLib="_grd_base.vcx" BaseClass="grid" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cAdresa.Header1' AS header WITH ;
|
||||
@@ -3205,6 +3336,70 @@ DEFINE CLASS frm_verificare_parteneri_istoric AS _frmbase OF "_frm_base.vcx"
|
||||
Visible = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataAnulImpScpTva.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Anulare scutire TVA", ;
|
||||
Name = "Header1", ;
|
||||
WordWrap = .T.
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataAnulImpScpTva.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1", ;
|
||||
ReadOnly = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataInactivare.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Data inactivare", ;
|
||||
Name = "Header1", ;
|
||||
WordWrap = .T.
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataInactivare.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1", ;
|
||||
ReadOnly = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataInceputScpTva.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Inceput scutire TVA", ;
|
||||
Name = "Header1", ;
|
||||
WordWrap = .T.
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataInceputScpTva.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1", ;
|
||||
ReadOnly = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataInceputTvaInc.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Inceput TVA incasare", ;
|
||||
Name = "Header1", ;
|
||||
WordWrap = .T.
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataInceputTvaInc.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1", ;
|
||||
ReadOnly = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataOra.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Creat la", ;
|
||||
@@ -3233,6 +3428,69 @@ DEFINE CLASS frm_verificare_parteneri_istoric AS _frmbase OF "_frm_base.vcx"
|
||||
Name = "Text1"
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataOravAnaf.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Data ANAF", ;
|
||||
Name = "Header1"
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataOravAnaf.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1", ;
|
||||
ReadOnly = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataReactivare.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Data reactivare", ;
|
||||
Name = "Header1", ;
|
||||
WordWrap = .T.
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataReactivare.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1", ;
|
||||
ReadOnly = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataSfarsitScpTva.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Sfarsit scutire TVA", ;
|
||||
Name = "Header1", ;
|
||||
WordWrap = .T.
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataSfarsitScpTva.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1", ;
|
||||
ReadOnly = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataSfarsitTvaInc.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Sfarsit TVA incasare", ;
|
||||
Name = "Header1", ;
|
||||
WordWrap = .T.
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataSfarsitTvaInc.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1", ;
|
||||
ReadOnly = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cDataTVAMfin.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Data TVA MFIN", ;
|
||||
@@ -3281,6 +3539,29 @@ DEFINE CLASS frm_verificare_parteneri_istoric AS _frmbase OF "_frm_base.vcx"
|
||||
Visible = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cInactiv._checkbox1' AS _checkbox WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "", ;
|
||||
Left = 19, ;
|
||||
Name = "_checkbox1", ;
|
||||
ReadOnly = .T., ;
|
||||
Top = 96
|
||||
*< END OBJECT: ClassLib="_baza.vcx" BaseClass="checkbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cInactiv.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Inactiv", ;
|
||||
Name = "Header1"
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cInactiv.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1"
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cJudet.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Judet", ;
|
||||
@@ -3362,6 +3643,29 @@ DEFINE CLASS frm_verificare_parteneri_istoric AS _frmbase OF "_frm_base.vcx"
|
||||
Visible = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cSplitTva._checkbox1' AS _checkbox WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "", ;
|
||||
Left = 19, ;
|
||||
Name = "_checkbox1", ;
|
||||
ReadOnly = .T., ;
|
||||
Top = 120
|
||||
*< END OBJECT: ClassLib="_baza.vcx" BaseClass="checkbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cSplitTva.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Split TVA", ;
|
||||
Name = "Header1"
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cSplitTva.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1"
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cStare.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Stare", ;
|
||||
@@ -3392,6 +3696,29 @@ DEFINE CLASS frm_verificare_parteneri_istoric AS _frmbase OF "_frm_base.vcx"
|
||||
Visible = .T.
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cTvaIncasare._checkbox1' AS _checkbox WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "", ;
|
||||
Left = 19, ;
|
||||
Name = "_checkbox1", ;
|
||||
ReadOnly = .T., ;
|
||||
Top = 144
|
||||
*< END OBJECT: ClassLib="_baza.vcx" BaseClass="checkbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cTvaIncasare.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "TVA incasare", ;
|
||||
Name = "Header1"
|
||||
*< END OBJECT: BaseClass="header" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cTvaIncasare.Text1' AS textbox WITH ;
|
||||
BackColor = 255,255,255, ;
|
||||
BorderStyle = 0, ;
|
||||
ForeColor = 0,0,0, ;
|
||||
Margin = 0, ;
|
||||
Name = "Text1"
|
||||
*< END OBJECT: BaseClass="textbox" />
|
||||
|
||||
ADD OBJECT '_grdbase1.cUtil.Header1' AS header WITH ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Creat de", ;
|
||||
|
||||
@@ -5018,7 +5018,7 @@ DEFINE CLASS frm_rulaje AS _frmbase OF "_frm_base.vcx"
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE pgframe.Page2.but_modifica_furnizor.Click
|
||||
loCaut = caut_partener()
|
||||
loCaut = caut_partener(,,,, .T., Thisform.dataact)
|
||||
IF TYPE('loCaut') = 'O' AND !ISNULL(loCaut)
|
||||
thisform.partener = ALLTRIM(loCaut.denumire)
|
||||
thisform.id_partener = loCaut.id_part
|
||||
|
||||
1
docs/.ultima_revizie
Normal file
1
docs/.ultima_revizie
Normal file
@@ -0,0 +1 @@
|
||||
2026-08-02
|
||||
@@ -1,127 +1,138 @@
|
||||
# Prompt: căutare și editare în cod VFP (foxbin2prg) — reutilizabil în orice proiect Visual FoxPro
|
||||
|
||||
Acest fișier conține un **prompt gata de copiat** pentru Claude Code (sau alt agent), care
|
||||
configurează și folosește sistemul `foxbin2prg` ca să poată **căuta** cod-sursă aflat **în interiorul
|
||||
fișierelor binare VFP** (`.vcx/.vct`, `.scx/.sct`, `.frx/.frt`, `.mnx/.mnt`, `.dbc/.dct`) într-un
|
||||
proiect nou — și, pentru `.vcx`/`.scx`, să poată și **modifica** acel cod direct pe text, cu
|
||||
write-back în binar (`txt2vcx.ps1`), fără trecere prin IDE-ul VFP.
|
||||
|
||||
Unealta e partajată și stă la `D:\ROA\UTIL\foxbin2prg\` — nu trebuie copiată per proiect. Doar
|
||||
spui agentului care e proiectul curent (folderul + fișierul `.pjx`).
|
||||
|
||||
---
|
||||
|
||||
## Cum se folosește
|
||||
|
||||
1. Deschide proiectul VFP în Claude Code.
|
||||
2. Copiază blocul de mai jos în prompt.
|
||||
3. Înlocuiește cele **3 valori** marcate `<<...>>` cu datele proiectului tău:
|
||||
- `<<RADACINA_PROIECT>>` = folderul rădăcină al proiectului (ex. `D:\ROA\ROAGEST`)
|
||||
- `<<FISIER_PJX>>` = calea către `.pjx` (ex. `D:\ROA\ROAGEST\roagest.pjx`)
|
||||
- `<<NUME_PROIECT>>` = etichetă scurtă pentru folderul de cache (ex. `roagest`)
|
||||
|
||||
---
|
||||
|
||||
## ▼▼▼ PROMPT DE COPIAT ▼▼▼
|
||||
|
||||
```
|
||||
Acest proiect este o aplicație Visual FoxPro 9. O mare parte din cod (proceduri, metode,
|
||||
parametri) NU stă în fișiere .prg, ci în interiorul fișierelor binare VFP: librării de clase
|
||||
(.vcx+.vct), forme (.scx+.sct), rapoarte (.frx+.frt), meniuri (.mnx+.mnt). Un grep direct pe
|
||||
acestea nu e lizibil (sunt tabele DBF cu memo binar).
|
||||
|
||||
Ca să poți căuta în acel cod, folosește unealta partajată foxbin2prg, care convertește binarele
|
||||
în reprezentarea lor TEXT (.vc2/.sc2/.fr2/.mn2/.dc2) într-un cache, și apoi caută în cache.
|
||||
|
||||
PARAMETRII PROIECTULUI CURENT:
|
||||
- Rădăcină proiect: <<RADACINA_PROIECT>>
|
||||
- Fișier proiect (.pjx): <<FISIER_PJX>>
|
||||
- Cache text: D:\ROA\_vfp_textcache\<<NUME_PROIECT>>
|
||||
|
||||
REGULA DE AUR: cache-ul text e sursa pentru CĂUTARE (toate tipurile de binar) și, DOAR pentru
|
||||
.vcx/.scx, și pentru EDITARE cu write-back (txt2vcx.ps1, vezi PAS 3). Pentru .frx/.mnx/.dbc
|
||||
textul rămâne doar pentru citire — modificările la ele se fac în IDE-ul VFP, pe binar.
|
||||
|
||||
PAS 1 — populează cache-ul text (la începutul sesiunii, sau după ce s-a modificat ceva în IDE).
|
||||
Rulează în PowerShell (e incremental — sare peste ce e deja la zi):
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Project '<<FISIER_PJX>>' -ProjectRoot '<<RADACINA_PROIECT>>' -CacheRoot 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>'
|
||||
|
||||
(Folosește un -CacheRoot distinct per proiect ca să nu amesteci cache-urile. Implicit scriptul
|
||||
convertește doar .vcx și .scx; pentru a include și rapoarte/meniuri adaugă: -Types vcx,scx,frx,mnx)
|
||||
|
||||
Dacă scriptul se plânge că lipsește FoxBin2Prg.EXE, trebuie compilat o singură dată: deschide
|
||||
'D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2' în VFP 9 și Build > Build Executable. Anunță-mă să fac asta.
|
||||
|
||||
PAS 2 — caută în cache cu unealta Grep (NU în binarele originale):
|
||||
|
||||
Grep pe folderul 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>' pentru numele de metodă/procedură/variabilă căutat.
|
||||
Ex.: caută "PROCEDURE do_salvare" sau numele tabelei/cursorului implicat.
|
||||
|
||||
CONVERSIE PUNCTUALĂ (un fișier sau folder care NU e în proiect, ex. o librărie din COMUN):
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Source 'CALE\catre\librarie.vcx' -CacheRoot 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>'
|
||||
|
||||
ALTE OPȚIUNI: -Force (reconvertește tot), -Clean (șterge cache-ul întâi).
|
||||
|
||||
PAS 3 — modificare de cod în .vcx/.scx (flux write-back pe text). Ordinea e obligatorie:
|
||||
|
||||
a. Investighează pe cache, propune modificarea și AȘTEAPTĂ ACORDUL pe abordare înainte să
|
||||
editezi ceva.
|
||||
b. Refresh cache (PAS 1) dacă a rulat vreo sesiune de IDE de la ultimul refresh (staleness-ul
|
||||
se verifică pe mtime și txt2vcx refuză corect scrierea peste modificări nevăzute). Înainte
|
||||
de write-back închide COMPLET VFP IDE și exe-ul aplicației — procesele reziduale țin lock
|
||||
pe binare.
|
||||
c. Editează .vc2/.sc2 BYTE-SAFE: formatul e position-sensitive (nu reformata/reflow linii),
|
||||
proprietățile sunt alfabetizate (una nouă se inserează la locul ei alfabetic). Headerul
|
||||
CPID="1252" poate minți despre codepage-ul real al diacriticelor — citește/scrie fișierul
|
||||
ca bytes (PowerShell), conținutul NOU doar ASCII; nu folosi unelte care re-encodează.
|
||||
d. Write-back:
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\txt2vcx.ps1' -TextFile 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>\Clase\lib.vc2' -ProjectRoot '<<RADACINA_PROIECT>>' -CacheRoot 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>'
|
||||
|
||||
Regenerează + compilează binarul în staging, verifică fidelitatea (roundtrip byte-identic
|
||||
față de textul editat) și abia apoi copiază binarul în proiect; la orice eșec proiectul
|
||||
rămâne neatins. Ținte sub COMUN\ cer flag-ul -AllowComun ȘI aprobare explicită — o
|
||||
modificare acolo afectează toate aplicațiile ROA.
|
||||
e. Diff lizibil pentru review: extrage binarul vechi din git (git show HEAD:cale > temp, atât
|
||||
.vcx cât și .vct), regenerează-i textul cu vcx2txt.ps1 -Source într-un folder temporar și
|
||||
compară cu cache-ul editat: git diff --no-index. COMMIT DOAR după ce omul confirmă pe diff
|
||||
și testează în IDE.
|
||||
|
||||
EXCEPȚII: pentru .mnx (GENMENU) și .frx (fragile la round-trip) nu există write-back — scrie
|
||||
propunerea de modificare într-un fișier docs/propuneri_<subiect>.md (cod + unde se inserează),
|
||||
iar aplicarea se face manual în IDE-ul VFP.
|
||||
|
||||
FLUX TIPIC: la prima sesiune rulează PAS 1 o dată, apoi caută cu Grep în cache (PAS 2). La
|
||||
sesiunile următoare rescrie doar ce s-a schimbat. Când citești codul unei metode, dă referințe
|
||||
fișier:linie din cache.
|
||||
```
|
||||
|
||||
## ▲▲▲ SFÂRȘIT PROMPT ▲▲▲
|
||||
|
||||
---
|
||||
|
||||
## Note pentru adaptare
|
||||
|
||||
- `<<NUME_PROIECT>>` îl poți pune orice etichetă scurtă (ex. `roagest`), doar ca numele
|
||||
folderului de cache să fie unic per proiect.
|
||||
- Ține cache-ul în `D:\ROA\_vfp_textcache\`, adică **în afara** folderului `foxbin2prg`. Motiv:
|
||||
`ReCreate_FoxBin2Prg.prg` face `Prg2Bin` recursiv pe tot folderul tool-ului și ar reconverti
|
||||
`.??2`-urile din orice cache aflat sub el înapoi în binare parazitare.
|
||||
- Scriptul citește lista de fișiere direct din `.pjx`, deci convertește **doar** ce folosește
|
||||
efectiv proiectul (rapid), nu tot `COMUN\`.
|
||||
- Cache-ul (`D:\ROA\_vfp_textcache\<proiect>`) e regenerabil și e în afara arborelui de versionare
|
||||
al proiectului (și în afara clonei foxbin2prg) — poate fi șters oricând.
|
||||
- Conversia NU necesită IDE-ul VFP deschis (folosește `FoxBin2Prg.EXE` compilat).
|
||||
- Fără backup-uri `.bak` lângă binarele din proiect — git e mecanismul de restore; `txt2vcx.ps1`
|
||||
ține o copie de siguranță doar în folderul temp al rulării.
|
||||
- Editările de volum se pot delega la subagenți (Sonnet, în background) — sesiunea principală
|
||||
orchestrează, verifică diff/fidelity și intervine doar la deblocări și decizii.
|
||||
- Detalii complete despre write-back (guard-uri, encoding, dialoguri VFP modale la text corupt,
|
||||
testul de regresie `test_roundtrip.ps1`): `D:\ROA\UTIL\foxbin2prg\CLAUDE.md`.
|
||||
- Exemplu funcțional, rodat pe ROAGEST: `D:\ROA\ROAGEST\docs\flux-editare-vfp-text.md` și
|
||||
`D:\ROA\ROAGEST\docs\CLAUDE.md` (modul de lucru complet, cu review pe diff înainte de commit).
|
||||
- Ghid complet doar-căutare (varianta ROAACNPRO, cu exemple): `D:\ROA\ROAACNPRO\docs\cautare_vcx_vct.md`.
|
||||
- Tabel corespondență binar → text: `.vcx`→`.vc2`, `.scx`→`.sc2`, `.frx`→`.fr2`, `.mnx`→`.mn2`,
|
||||
`.dbc`→`.dc2`, `.lbx`→`.lb2`.
|
||||
# Prompt: căutare și editare în cod VFP (foxbin2prg) — reutilizabil în orice proiect Visual FoxPro
|
||||
|
||||
**Prompt gata de copiat** pentru Claude Code (sau alt agent), care configurează și folosește
|
||||
sistemul `foxbin2prg` ca să poată **căuta** cod-sursă aflat **în interiorul fișierelor binare VFP**
|
||||
(`.vcx/.vct`, `.scx/.sct`, `.frx/.frt`, `.mnx/.mnt`, `.dbc/.dct`) într-un proiect nou — și, pentru
|
||||
`.vcx`/`.scx`, să poată și **modifica** acel cod direct pe text, cu write-back în binar
|
||||
(`txt2vcx.ps1`), fără trecere prin IDE-ul VFP.
|
||||
|
||||
Unealta e partajată, la `D:\ROA\UTIL\foxbin2prg\` — nu se copiază per proiect. Doar spui agentului
|
||||
care e proiectul curent (folderul + fișierul `.pjx`).
|
||||
|
||||
---
|
||||
|
||||
## Cum se folosește
|
||||
|
||||
1. Deschide proiectul VFP în Claude Code.
|
||||
2. Copiază blocul de mai jos în prompt.
|
||||
3. Înlocuiește cele **3 valori** marcate `<<...>>`:
|
||||
- `<<RADACINA_PROIECT>>` = folderul rădăcină al proiectului (ex. `D:\ROA\ROAGEST`)
|
||||
- `<<FISIER_PJX>>` = calea către `.pjx` (ex. `D:\ROA\ROAGEST\roagest.pjx`)
|
||||
- `<<NUME_PROIECT>>` = etichetă scurtă pentru folderul de cache (ex. `roagest`)
|
||||
|
||||
---
|
||||
|
||||
## ▼▼▼ PROMPT DE COPIAT ▼▼▼
|
||||
|
||||
```
|
||||
Acest proiect este o aplicație Visual FoxPro 9. O mare parte din cod (proceduri, metode,
|
||||
parametri) NU stă în fișiere .prg, ci în interiorul fișierelor binare VFP: librării de clase
|
||||
(.vcx+.vct), forme (.scx+.sct), rapoarte (.frx+.frt), meniuri (.mnx+.mnt). Un grep direct pe
|
||||
acestea nu e lizibil (sunt tabele DBF cu memo binar).
|
||||
|
||||
Ca să poți căuta în acel cod, folosește unealta partajată foxbin2prg, care convertește binarele
|
||||
în reprezentarea lor TEXT (.vc2/.sc2/.fr2/.mn2/.dc2) într-un cache, și apoi caută în cache.
|
||||
|
||||
PARAMETRII PROIECTULUI CURENT:
|
||||
- Rădăcină proiect: <<RADACINA_PROIECT>>
|
||||
- Fișier proiect (.pjx): <<FISIER_PJX>>
|
||||
- Cache text: D:\ROA\_vfp_textcache\<<NUME_PROIECT>>
|
||||
|
||||
REGULA DE AUR: cache-ul text e sursa pentru CĂUTARE (toate tipurile de binar) și, DOAR pentru
|
||||
.vcx/.scx, și pentru EDITARE cu write-back (txt2vcx.ps1, vezi PAS 3). Pentru .frx/.mnx/.dbc
|
||||
textul rămâne doar pentru citire — modificările la ele se fac în IDE-ul VFP, pe binar.
|
||||
|
||||
PAS 1 — populează cache-ul text (la începutul sesiunii, sau după ce s-a modificat ceva în IDE).
|
||||
Rulează în PowerShell (e incremental — sare peste ce e deja la zi):
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Project '<<FISIER_PJX>>' -ProjectRoot '<<RADACINA_PROIECT>>' -CacheRoot 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>'
|
||||
|
||||
(Folosește un -CacheRoot distinct per proiect ca să nu amesteci cache-urile. Implicit scriptul
|
||||
convertește doar .vcx și .scx; pentru a include și rapoarte/meniuri adaugă: -Types vcx,scx,frx,mnx)
|
||||
|
||||
Dacă scriptul se plânge că lipsește FoxBin2Prg.EXE, trebuie compilat o singură dată: deschide
|
||||
'D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2' în VFP 9 și Build > Build Executable. Anunță-mă să fac asta.
|
||||
|
||||
PAS 2 — caută în cache cu unealta Grep (NU în binarele originale):
|
||||
|
||||
Grep pe folderul 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>' pentru numele de metodă/procedură/variabilă căutat.
|
||||
Ex.: caută "PROCEDURE do_salvare" sau numele tabelei/cursorului implicat.
|
||||
|
||||
PAS 2b — atribuie rezultatele clasei/metodei care le conține. Grep dă doar fișier:linie, iar
|
||||
într-un .vc2 antetul clasei poate fi cu mii de linii mai sus și ~2/3 din fișier e metadata:
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1' -CacheRoot 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>' -ProjectRoot '<<RADACINA_PROIECT>>' -Grep 'expresie' -CodeOnly
|
||||
|
||||
Alte moduri: -Where 'fisier.vc2:1234' (cine deține linia), -Find 'nume' (unde e DEFINIT, nu și
|
||||
apelurile), -Class 'nume_clasa' (lanț de moștenire + metode cu intervalele de linii).
|
||||
Indexul se reconstruiește singur din cache; rulează PAS 1 înainte.
|
||||
OBLIGATORIU înainte de PAS 3: intervalul exact al metodei. Într-un .vc2 cu multe clase, Init,
|
||||
Show, do_adauga există în aproape fiecare — fără interval editezi metoda din altă clasă.
|
||||
|
||||
CONVERSIE PUNCTUALĂ (un fișier sau folder care NU e în proiect, ex. o librărie din COMUN):
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Source 'CALE\catre\librarie.vcx' -CacheRoot 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>'
|
||||
|
||||
ALTE OPȚIUNI: -Force (reconvertește tot), -Clean (șterge cache-ul întâi).
|
||||
|
||||
PAS 3 — modificare de cod în .vcx/.scx (flux write-back pe text). Ordinea e obligatorie:
|
||||
|
||||
a. Investighează pe cache, propune modificarea și AȘTEAPTĂ ACORDUL pe abordare înainte să
|
||||
editezi ceva.
|
||||
b. Refresh cache (PAS 1) dacă a rulat vreo sesiune de IDE de la ultimul refresh (staleness-ul
|
||||
se verifică pe mtime și txt2vcx refuză corect scrierea peste modificări nevăzute). Înainte
|
||||
de write-back închide COMPLET VFP IDE și exe-ul aplicației — procesele reziduale țin lock
|
||||
pe binare.
|
||||
c. Editează .vc2/.sc2 BYTE-SAFE: formatul e position-sensitive (nu reformata/reflow linii),
|
||||
proprietățile sunt alfabetizate (una nouă se inserează la locul ei alfabetic). Headerul
|
||||
CPID="1252" poate minți despre codepage-ul real al diacriticelor — citește/scrie fișierul
|
||||
ca bytes (PowerShell), conținutul NOU doar ASCII; nu folosi unelte care re-encodează.
|
||||
d. Write-back:
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\txt2vcx.ps1' -TextFile 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>\Clase\lib.vc2' -ProjectRoot '<<RADACINA_PROIECT>>' -CacheRoot 'D:\ROA\_vfp_textcache\<<NUME_PROIECT>>'
|
||||
|
||||
Regenerează + compilează binarul în staging, verifică fidelitatea (roundtrip byte-identic
|
||||
față de textul editat) și abia apoi copiază binarul în proiect; la orice eșec proiectul
|
||||
rămâne neatins. Ținte sub COMUN\ cer flag-ul -AllowComun ȘI aprobare explicită — o
|
||||
modificare acolo afectează toate aplicațiile ROA.
|
||||
e. Diff lizibil pentru review: extrage binarul vechi din git (git show HEAD:cale > temp, atât
|
||||
.vcx cât și .vct), regenerează-i textul cu vcx2txt.ps1 -Source într-un folder temporar și
|
||||
compară cu cache-ul editat: git diff --no-index. COMMIT DOAR după ce omul confirmă pe diff
|
||||
și testează în IDE.
|
||||
|
||||
EXCEPȚII: pentru .mnx (GENMENU) și .frx (fragile la round-trip) nu există write-back — scrie
|
||||
propunerea de modificare într-un fișier docs/propuneri_<subiect>.md (cod + unde se inserează),
|
||||
iar aplicarea se face manual în IDE-ul VFP.
|
||||
|
||||
FLUX TIPIC: la prima sesiune rulează PAS 1 o dată, apoi caută cu Grep în cache (PAS 2). La
|
||||
sesiunile următoare rescrie doar ce s-a schimbat. Când citești codul unei metode, dă referințe
|
||||
fișier:linie din cache.
|
||||
```
|
||||
|
||||
## ▲▲▲ SFÂRȘIT PROMPT ▲▲▲
|
||||
|
||||
---
|
||||
|
||||
## Note pentru adaptare
|
||||
|
||||
- `<<NUME_PROIECT>>` poate fi orice etichetă scurtă (ex. `roagest`), unică per proiect (numele
|
||||
folderului de cache).
|
||||
- Ține cache-ul în `D:\ROA\_vfp_textcache\`, adică **în afara** folderului `foxbin2prg`. Motiv:
|
||||
`ReCreate_FoxBin2Prg.prg` face `Prg2Bin` recursiv pe tot folderul tool-ului și ar reconverti
|
||||
`.??2`-urile din orice cache aflat sub el înapoi în binare parazitare.
|
||||
- Scriptul citește lista de fișiere direct din `.pjx`, deci convertește doar ce folosește efectiv
|
||||
proiectul (rapid), nu tot `COMUN\`.
|
||||
- Cache-ul e regenerabil, în afara arborelui de versionare al proiectului (și al clonei
|
||||
foxbin2prg) — poate fi șters oricând.
|
||||
- Conversia NU necesită IDE-ul VFP deschis (folosește `FoxBin2Prg.EXE` compilat).
|
||||
- Fără backup-uri `.bak` lângă binarele din proiect — git e mecanismul de restore; `txt2vcx.ps1`
|
||||
ține o copie de siguranță doar în folderul temp al rulării.
|
||||
- Editările de volum se pot delega la subagenți (Sonnet, în background) — sesiunea principală
|
||||
orchestrează, verifică diff/fidelity și intervine doar la deblocări și decizii.
|
||||
- Detalii complete despre write-back (guard-uri, encoding, dialoguri VFP modale la text corupt,
|
||||
testul de regresie `test_roundtrip.ps1`): `D:\ROA\UTIL\foxbin2prg\CLAUDE.md`.
|
||||
- Exemplu funcțional, rodat pe ROAGEST: `D:\ROA\ROAGEST\docs\flux-editare-vfp-text.md` și
|
||||
`D:\ROA\ROAGEST\docs\CLAUDE.md` (modul de lucru complet, cu review pe diff înainte de commit).
|
||||
- Ghid complet doar-căutare (varianta ROAACNPRO, cu exemple): `D:\ROA\ROAACNPRO\docs\cautare_vcx_vct.md`.
|
||||
- Tabel corespondență binar → text: `.vcx`→`.vc2`, `.scx`→`.sc2`, `.frx`→`.fr2`, `.mnx`→`.mn2`,
|
||||
`.dbc`→`.dc2`, `.lbx`→`.lb2`.
|
||||
|
||||
14
docs/capcana_grid_controlsource.md
Normal file
14
docs/capcana_grid_controlsource.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Capcana: grid needitabil cand formularul are 2+ grid-uri
|
||||
|
||||
Pe un formular cu doua sau mai multe grid-uri, gridul ale carui coloane au `ControlSource`
|
||||
**necalificat** (`camp` in loc de `alias.camp`) devine needitabil - nu se poate scrie in celule.
|
||||
VFP rezolva numele necalificat pe workarea curenta, care e a celuilalt grid/cursor.
|
||||
|
||||
Solutii:
|
||||
|
||||
- **Recomandat**: `ControlSource` calificat complet (`alias.camp`) pe fiecare coloana. Obligatoriu
|
||||
cand sunt implicate mai multe cursoare/tabele.
|
||||
- Alternativa (doar cu un singur cursor sursa): `SELECT <alias>` inainte de `DO FORM` /
|
||||
`CreateObject()`, ca workarea curenta la instantiere sa fie cea corecta.
|
||||
|
||||
Constatat pe ROAGEST (coloana "pret lei" nu accepta scriere pana la calificarea ControlSource-ului).
|
||||
17
docs/capcana_grid_preferinte_utilizator.md
Normal file
17
docs/capcana_grid_preferinte_utilizator.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Capcana: coloana noua intr-un grid existent ajunge la coada (preferinte GridExtras)
|
||||
|
||||
`GridExtras` (`COMUN\utile\GridExtras\gridextras.vc2:1051`, `restoregridpreferences` /
|
||||
`savegridpreferences`) salveaza **per utilizator** latimea si ordinea coloanelor fiecarui grid,
|
||||
in `%APPDATA%\...\gridprefs.tmp`, sub cheia `SYS(1272, grid)` (ex. `frm_modific2024.grid1`).
|
||||
Salvarea se face live, la `columnmoved`/`columnresize`, nu la iesirea din formular.
|
||||
|
||||
Consecinta: `ColumnOrder` setat in clasa e neutralizat la runtime pentru orice utilizator care a
|
||||
deschis deja formularul inainte de livrare - `gridextra1.setup()` restaureaza ordinea veche, iar
|
||||
coloana nou adaugata (care nu exista in preferinte) ajunge ultima.
|
||||
|
||||
Solutie: repozitionare la runtime, in `Show()`, **dupa** `gridextra1.setup()`, aplicata o singura
|
||||
data - cat timp preferintele salvate nu acopera toate coloanele (implementat pe
|
||||
`frm_modific2024`, `COMUN\clase\omodificari.vc2`, coloana `nnir`).
|
||||
|
||||
La testare: pozitia coloanei nu e o asertiune stabila intre masini. Se asertesteaza tare
|
||||
`ControlSource` si `ReadOnly`; `ColumnOrder` ramane informativ.
|
||||
@@ -1,139 +1,183 @@
|
||||
# Căutare în codul din librăriile/formele VFP (`.vcx`/`.vct`, `.scx`/`.sct`, ...)
|
||||
|
||||
Partajat între proiectele ROA* (companion narativ la `PROMPT_cautare_vfp.md` din acest folder,
|
||||
care e varianta "prompt de copiat" — acest fișier e ghidul de referință complet, cu exemple).
|
||||
|
||||
Cum se caută cod-sursă (proceduri, metode, parametri) care **nu** stă în fișiere `.prg`, ci
|
||||
în interiorul fișierelor binare VFP: librării de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`),
|
||||
rapoarte (`.frx`+`.frt`), meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`).
|
||||
|
||||
## De ce e nevoie de asta
|
||||
|
||||
Un `.vcx` este de fapt o **tabelă DBF**: codul metodelor stă în câmpuri memo în `.vct`. Un
|
||||
`grep` direct pe `.vct` *găsește* textul, dar îl vede ca fișier binar (octeți `\0` între linii),
|
||||
fără numere de linie utile și greu de citit. Soluția: convertim binarul în reprezentarea lui
|
||||
**TEXT** (`.vc2`, `.sc2`, …) — un PRG-style lizibil, cu metode sortate alfabetic — și căutăm
|
||||
în text cu `grep`/`Grep`.
|
||||
|
||||
> **Regula de aur:** textul generat e **doar pentru citire/căutare**, CU O EXCEPȚIE: pentru
|
||||
> `.vcx`/`.scx` se poate și edita pe text, cu write-back în binar (`txt2vcx.ps1`) — vezi
|
||||
> `PROMPT_cautare_vfp.md` pasul 3 pentru fluxul complet (ordine obligatorie, encoding,
|
||||
> fidelity check). Pentru `.frx`/`.mnx`/`.dbc` nu există write-back — modificările se fac tot
|
||||
> în **IDE-ul VFP**.
|
||||
|
||||
## Unelte disponibile (verificate)
|
||||
|
||||
| Unealtă | Cale | Rol | Recomandare |
|
||||
|---|---|---|---|
|
||||
| **FoxBin2Prg** | `D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE` | Binar VFP ⇄ text bidirecțional (`.vc2/.sc2/.fr2/.mn2/.dc2/.lb2`) | **De folosit.** Complet, fidel, include corpul metodelor, parametri, comentarii |
|
||||
| vcx2prg | `D:\ROA\UTIL\vcx2prg\x2prg.prg` | Doar `.vcx` → `.prg` *compilabil* | Alternativă; mai vechi, doar clase, necesită IDE VFP deschis pentru a rula forma |
|
||||
| prgtovcx | `D:\ROA\UTIL\prgtovcx\prgtovcx.PRG` | Invers: `.prg` → `.vcx` | **Nu** pentru căutare (e direcția opusă) |
|
||||
|
||||
FoxBin2Prg e prima alegere: rulează din linia de comandă fără IDE deschis (EXE compilat), acoperă
|
||||
toate tipurile de container, și produce text mult mai fidel decât vcx2prg.
|
||||
|
||||
> Dacă `FoxBin2Prg.EXE` lipsește, se compilează o singură dată: deschide
|
||||
> `D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2` în VFP 9 și *Build > Build Executable*. Lângă EXE trebuie
|
||||
> să existe `filename_caps.exe` și fișierele `props*.txt` (sunt deja în folder).
|
||||
|
||||
## Mod recomandat: scriptul `vcx2txt.ps1`
|
||||
|
||||
`D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1` automatizează tot: copiază binarul + memo-ul într-un
|
||||
**cache** care oglindește structura proiectului (ca să nu murdărească arborele SVN), rulează
|
||||
FoxBin2Prg, păstrează doar fișierul text. E **incremental** (sare peste ce e deja la zi).
|
||||
|
||||
Parametrizează scriptul cu proiectul curent și un cache separat per proiect (nu amesteca
|
||||
cache-urile mai multor proiecte ROA):
|
||||
|
||||
```powershell
|
||||
# DOAR fișierele proiectului curent (recomandat, rapid) -> cache text propriu
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||
-CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>'
|
||||
|
||||
# include și rapoartele (.frx) și meniurile (.mnx)
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||
-CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>' -Types vcx,scx,frx,mnx
|
||||
|
||||
# conversie punctuală a unui fișier sau folder (chiar dacă NU e în proiect, ex. o clasă din COMUN)
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source '<RADACINA_PROIECT>\COMUN\clase\caut.vcx'
|
||||
|
||||
# rebuild curat (șterge cache-ul întâi) / forțează reconversia
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||
-CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>' -Clean
|
||||
```
|
||||
|
||||
Exemplu concret (ROAAUTO):
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project D:\ROA\ROAAUTO\roaauto.pjx -ProjectRoot D:\ROA\ROAAUTO `
|
||||
-CacheRoot D:\ROA\UTIL\foxbin2prg\_textcache_roaauto
|
||||
```
|
||||
|
||||
Rezultatul ajunge în cache-ul indicat, cu aceeași structură de directoare ca proiectul (ex.:
|
||||
`_textcache_roaauto\Clase\odevize.vc2`, `_textcache_roaauto\comun\clase\_frm_base.vc2`). Apoi:
|
||||
|
||||
```bash
|
||||
# cu unealta Grep (preferat) sau grep:
|
||||
grep -rn "PROCEDURE do_calcul_tarife" "D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>"
|
||||
grep -rln "factura_salvare" "D:\ROA\UTIL\foxbin2prg\_textcache_<nume_proiect>" # ce clase ating subiectul
|
||||
```
|
||||
|
||||
Flux tipic pentru o problemă: rulează scriptul cu parametrii de mai sus o dată (populează
|
||||
cache-ul), apoi caută cu `Grep` în cache. La sesiuni următoare rescrie doar ce s-a schimbat
|
||||
(incremental). Dacă ai nevoie de o librărie din `COMUN\` care nu e în proiect, convertește-o
|
||||
punctual cu `-Source`.
|
||||
|
||||
## Alternativă manuală (fără script)
|
||||
|
||||
FoxBin2Prg scrie textul **lângă sursă**. Ca să nu murdărești folderul de clase al proiectului,
|
||||
copiază perechea binar+memo într-un folder temporar și convertește acolo:
|
||||
|
||||
```powershell
|
||||
# .vcx -> .vc2 (cType gol = extensia decide direcția BIN2PRG)
|
||||
Copy-Item D:\ROA\<proiect>\Clase\odevize.vcx, D:\ROA\<proiect>\Clase\odevize.vct D:\tmp\
|
||||
& 'D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE' 'D:\tmp\odevize.vcx' '' '' '' '1' '0' '1'
|
||||
# => D:\tmp\odevize.vc2
|
||||
```
|
||||
|
||||
Pozițiile parametrilor folosite: `fișier, cType, cTextName, lGenText, cDontShowErrors=1,
|
||||
cDebug=0, cDontShowProgress=1`. **Lasă `cType` gol** — extensia (`.vcx`) determină direcția.
|
||||
(Nu da explicit `"BIN2PRG"` pentru un singur fișier: în acel mod EXE-ul așteaptă un *director*.)
|
||||
|
||||
Detalii complete de parametri: `D:\ROA\UTIL\foxbin2prg\docs\FoxBin2Prg_Run.md`.
|
||||
|
||||
## Soluție rapidă „murdară" (un singur fișier, fără conversie)
|
||||
|
||||
Pentru o verificare rapidă „există metoda X undeva în librărie?", `grep` merge direct pe `.vct`
|
||||
(o vede ca binar, dar găsește potrivirile):
|
||||
|
||||
```bash
|
||||
grep -c "PROCEDURE" "D:\ROA\<proiect>\Clase\odevize.VCT"
|
||||
grep -a -o "PROCEDURE [a-zA-Z0-9_]*" "D:\ROA\<proiect>\Clase\odevize.VCT"
|
||||
```
|
||||
|
||||
Bun pentru „da/nu" și nume de metode; pentru citit corpul/contextul, folosește conversia în text.
|
||||
|
||||
## Corespondență extensii binar → text
|
||||
|
||||
| Container | Binar (+memo) | Text |
|
||||
|---|---|---|
|
||||
| Librărie clase | `.vcx` + `.vct` | `.vc2` |
|
||||
| Formă | `.scx` + `.sct` | `.sc2` |
|
||||
| Raport | `.frx` + `.frt` | `.fr2` |
|
||||
| Etichetă | `.lbx` + `.lbt` | `.lb2` |
|
||||
| Meniu | `.mnx` + `.mnt` | `.mn2` |
|
||||
| Bază de date | `.dbc` + `.dct` | `.dc2` |
|
||||
|
||||
## Note
|
||||
|
||||
- Codul aplicației stă mai ales în `Clase\*.vcx`; o mare parte din `.vcx`-uri sunt în
|
||||
`COMUN\` (framework partajat între toate aplicațiile ROA — vezi `CLAUDE.md` per proiect).
|
||||
- Cache-ul text e regenerabil și e în afara arborelui SVN/git al proiectului — poate fi șters
|
||||
oricând.
|
||||
- Conversia **nu** necesită IDE-ul VFP deschis (folosește EXE-ul compilat).
|
||||
- Vezi și [conventie_encoding_cp1252.md](conventie_encoding_cp1252.md) — capcană de encoding la
|
||||
editarea `.sc2`/`.vc2` (nu doar la căutare).
|
||||
# Căutare în codul din librăriile/formele VFP (`.vcx`/`.vct`, `.scx`/`.sct`, ...)
|
||||
|
||||
Partajat între proiectele ROA* (companion narativ la `PROMPT_cautare_vfp.md` din acest folder —
|
||||
varianta "prompt de copiat" — acest fișier e ghidul de referință complet, cu exemple).
|
||||
|
||||
Căutare de cod-sursă (proceduri, metode, parametri) care **nu** stă în `.prg`, ci în interiorul
|
||||
binarelor VFP: librării de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`), rapoarte (`.frx`+`.frt`),
|
||||
meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`).
|
||||
|
||||
## De ce e nevoie de asta
|
||||
|
||||
Un `.vcx` e o **tabelă DBF**: codul metodelor stă în câmpuri memo în `.vct`. `grep` direct pe
|
||||
`.vct` găsește textul dar ca binar (octeți `\0` între linii), fără numere de linie și greu de
|
||||
citit. Soluția: convertim binarul în reprezentarea lui **TEXT** (`.vc2`, `.sc2`, …) — PRG-style
|
||||
lizibil, metode sortate alfabetic — și căutăm în text cu `grep`/`Grep`.
|
||||
|
||||
> **Regula de aur:** textul generat e **doar pentru citire/căutare**, CU O EXCEPȚIE: pentru
|
||||
> `.vcx`/`.scx` se poate și edita pe text, cu write-back în binar (`txt2vcx.ps1`) — vezi
|
||||
> `PROMPT_cautare_vfp.md` pasul 3 (ordine obligatorie, encoding, fidelity check). Pentru
|
||||
> `.frx`/`.mnx`/`.dbc` nu există write-back — modificările se fac tot în **IDE-ul VFP**.
|
||||
|
||||
## Unelte disponibile (verificate)
|
||||
|
||||
| Unealtă | Cale | Rol | Recomandare |
|
||||
|---|---|---|---|
|
||||
| **FoxBin2Prg** | `D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE` | Binar VFP ⇄ text bidirecțional (`.vc2/.sc2/.fr2/.mn2/.dc2/.lb2`) | **De folosit.** Fidel, include corpul metodelor, parametri, comentarii |
|
||||
| vcx2prg | `D:\ROA\UTIL\vcx2prg\x2prg.prg` | Doar `.vcx` → `.prg` compilabil | Alternativă mai veche, doar clase, necesită IDE VFP deschis |
|
||||
| prgtovcx | `D:\ROA\UTIL\prgtovcx\prgtovcx.PRG` | Invers: `.prg` → `.vcx` | **Nu** pentru căutare (direcție opusă) |
|
||||
|
||||
FoxBin2Prg e prima alegere: rulează din linia de comandă fără IDE deschis (EXE compilat), acoperă
|
||||
toate tipurile de container, text mai fidel decât vcx2prg.
|
||||
|
||||
> Dacă `FoxBin2Prg.EXE` lipsește: deschide `D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2` în VFP 9 și
|
||||
> *Build > Build Executable*. Lângă EXE trebuie să existe `filename_caps.exe` și `props*.txt`
|
||||
> (deja în folder).
|
||||
|
||||
## Mod recomandat: scriptul `vcx2txt.ps1`
|
||||
|
||||
`D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1` copiază binarul + memo-ul într-un **cache** care oglindește
|
||||
structura proiectului (nu murdărește arborele SVN), rulează FoxBin2Prg, păstrează doar textul.
|
||||
**Incremental** (sare peste ce e deja la zi).
|
||||
|
||||
```powershell
|
||||
# DOAR fișierele proiectului curent (recomandat, rapid) -> cache text propriu
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||
-CacheRoot 'D:\ROA\_vfp_textcache\<nume_proiect>'
|
||||
|
||||
# include și rapoartele (.frx) și meniurile (.mnx)
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||
-CacheRoot 'D:\ROA\_vfp_textcache\<nume_proiect>' -Types vcx,scx,frx,mnx
|
||||
|
||||
# conversie punctuală a unui fișier/folder (chiar dacă NU e în proiect, ex. o clasă din COMUN)
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source '<RADACINA_PROIECT>\COMUN\clase\caut.vcx'
|
||||
|
||||
# rebuild curat (șterge cache-ul întâi) / forțează reconversia
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project '<RADACINA_PROIECT>\<proiect>.pjx' -ProjectRoot '<RADACINA_PROIECT>' `
|
||||
-CacheRoot 'D:\ROA\_vfp_textcache\<nume_proiect>' -Clean
|
||||
```
|
||||
|
||||
Exemplu (ROAAUTO):
|
||||
|
||||
```powershell
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project D:\ROA\ROAAUTO\roaauto.pjx -ProjectRoot D:\ROA\ROAAUTO `
|
||||
-CacheRoot D:\ROA\_vfp_textcache\roaauto
|
||||
```
|
||||
|
||||
> Cache-ul trebuie să stea **în afara** folderului `D:\ROA\UTIL\foxbin2prg`: `ReCreate_FoxBin2Prg.prg`
|
||||
> face `Prg2Bin` recursiv pe tot folderul uneltei și ar reconverti `.??2`-urile din cache în binare
|
||||
> rătăcite.
|
||||
|
||||
Rezultatul ajunge în cache, cu aceeași structură de directoare ca proiectul (ex.:
|
||||
`roaauto\Clase\odevize.vc2`, `roaauto\comun\clase\_frm_base.vc2`). Apoi:
|
||||
|
||||
```bash
|
||||
grep -rn "PROCEDURE do_calcul_tarife" "D:\ROA\_vfp_textcache\<nume_proiect>"
|
||||
grep -rln "factura_salvare" "D:\ROA\_vfp_textcache\<nume_proiect>" # ce clase ating subiectul
|
||||
```
|
||||
|
||||
Flux tipic: rulează scriptul o dată (populează cache-ul), apoi caută cu `Grep` în cache. La
|
||||
sesiuni următoare rescrie doar ce s-a schimbat (incremental). Pentru o librărie din `COMUN\` care
|
||||
nu e în proiect, convertește-o punctual cu `-Source`.
|
||||
|
||||
## Indexul de simboluri: `vfp_symbols.ps1`
|
||||
|
||||
`grep` spune *unde* e textul, nu *în ce metodă*. Într-un `.vc2` asta contează: fișierele au uzual
|
||||
zeci de mii de linii, din care ~2/3 sunt proprietăți și metadata (nu cod), iar antetul clasei poate
|
||||
fi cu mii de linii deasupra potrivirii. `D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1` reține intervalul
|
||||
de linii al fiecărei clase/metode/proceduri — din cache-ul text **și** din `.prg`-urile proiectului
|
||||
— și etichetează rezultatele.
|
||||
|
||||
```powershell
|
||||
$s = 'D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1'
|
||||
$c = @('-CacheRoot', 'D:\ROA\_vfp_textcache\<nume_proiect>', '-ProjectRoot', '<RADACINA_PROIECT>')
|
||||
|
||||
# căutare etichetată cu clasa.metoda; -CodeOnly taie potrivirile din metadata/proprietăți
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Grep '<expresie>' -CodeOnly
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Where '<fisier>.vc2:<linie>' # cine deține linia
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Find '<nume>' # unde e DEFINIT
|
||||
powershell -ExecutionPolicy Bypass -File $s @c -Class '<nume_clasa>' # moștenire + metode
|
||||
```
|
||||
|
||||
Exemplu (ROAACNPRO — parametrii impliciți ai scriptului țintesc deja acest proiect):
|
||||
|
||||
```
|
||||
> vfp_symbols.ps1 -Grep 'calcul_cheiaj' -CodeOnly
|
||||
clase\oacnpro.vc2:14937: [frm_tranzit.do_executa] llSucces = calcul_cheiaj(m.lcVyeIds)
|
||||
> vfp_symbols.ps1 -Class oApp
|
||||
oApp (roaacnpro.prg:88) -> RoaApp (roa.prg:1) -> Custom (clasă de bază VFP)
|
||||
```
|
||||
|
||||
Când merită în locul unui `grep` direct:
|
||||
|
||||
- **înainte de o editare cu `txt2vcx.ps1`** — `-Where`/`-Class` dau intervalul exact al metodei.
|
||||
Într-un `.vc2` cu 15 clase, `Init`, `Show`, `do_adauga`, `do_executa2` există în aproape fiecare;
|
||||
fără interval e ușor să nimerești metoda cu același nume din altă clasă;
|
||||
- **rezultate multe** — `-CodeOnly` arată doar codul (pe `goExecutor` în ROAACNPRO: 1401 potriviri
|
||||
de cod din 1505, restul metadata);
|
||||
- **„definit sau doar apelat?"** — `-Find` dă doar definiția, `grep` dă tot;
|
||||
- **moștenire** — `-Class` arată lanțul cu fișier:linie, deci se vede dacă o metodă e suprascrisă
|
||||
local sau vine din `COMUN`.
|
||||
|
||||
Indexul (`_symbols.tsv`, în rădăcina cache-ului) se reconstruiește singur când cache-ul e mai nou
|
||||
(~4 s pentru ~200 de fișiere); e regenerabil, se poate șterge oricând. Rulează întâi `vcx2txt.ps1`:
|
||||
indexul e derivat din cache, deci nu poate ști de modificări făcute în IDE și neconvertite.
|
||||
|
||||
Limite: nu rezolvă apelurile indirecte (`EVALUATE`, `SET CLASSLIB`) — dă candidații, nu
|
||||
certitudinea. Clasele de bază VFP (`form`, `custom`) apar ca neindexate: normal, n-au sursă în
|
||||
proiect. Copiile vechi de `.prg` din subfoldere (ex. `COMUN\programe\roa\`) sunt excluse implicit
|
||||
prin `-ExcludePrg`; dă `-ExcludePrg ''` ca să vezi tot.
|
||||
|
||||
## Alternativă manuală (fără script)
|
||||
|
||||
FoxBin2Prg scrie textul **lângă sursă**. Ca să nu murdărești folderul de clase al proiectului,
|
||||
copiază perechea binar+memo într-un folder temporar și convertește acolo:
|
||||
|
||||
```powershell
|
||||
# .vcx -> .vc2 (cType gol = extensia decide direcția BIN2PRG)
|
||||
Copy-Item D:\ROA\<proiect>\Clase\odevize.vcx, D:\ROA\<proiect>\Clase\odevize.vct D:\tmp\
|
||||
& 'D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE' 'D:\tmp\odevize.vcx' '' '' '' '1' '0' '1'
|
||||
# => D:\tmp\odevize.vc2
|
||||
```
|
||||
|
||||
Poziții parametri: `fișier, cType, cTextName, lGenText, cDontShowErrors=1, cDebug=0,
|
||||
cDontShowProgress=1`. **Lasă `cType` gol** — extensia (`.vcx`) determină direcția. (Nu da explicit
|
||||
`"BIN2PRG"` pentru un singur fișier: în acel mod EXE-ul așteaptă un *director*.)
|
||||
|
||||
Detalii complete de parametri: `D:\ROA\UTIL\foxbin2prg\docs\FoxBin2Prg_Run.md`.
|
||||
|
||||
## Soluție rapidă „murdară" (un singur fișier, fără conversie)
|
||||
|
||||
Pentru „există metoda X undeva în librărie?", `grep` merge direct pe `.vct` (îl vede ca binar, dar
|
||||
găsește potrivirile):
|
||||
|
||||
```bash
|
||||
grep -c "PROCEDURE" "D:\ROA\<proiect>\Clase\odevize.VCT"
|
||||
grep -a -o "PROCEDURE [a-zA-Z0-9_]*" "D:\ROA\<proiect>\Clase\odevize.VCT"
|
||||
```
|
||||
|
||||
Bun pentru „da/nu" și nume de metode; pentru corp/context, folosește conversia în text.
|
||||
|
||||
## Corespondență extensii binar → text
|
||||
|
||||
| Container | Binar (+memo) | Text |
|
||||
|---|---|---|
|
||||
| Librărie clase | `.vcx` + `.vct` | `.vc2` |
|
||||
| Formă | `.scx` + `.sct` | `.sc2` |
|
||||
| Raport | `.frx` + `.frt` | `.fr2` |
|
||||
| Etichetă | `.lbx` + `.lbt` | `.lb2` |
|
||||
| Meniu | `.mnx` + `.mnt` | `.mn2` |
|
||||
| Bază de date | `.dbc` + `.dct` | `.dc2` |
|
||||
|
||||
## Note
|
||||
|
||||
- Codul aplicației stă mai ales în `Clase\*.vcx`; multe `.vcx`-uri sunt în `COMUN\` (framework
|
||||
partajat între toate aplicațiile ROA — vezi `CLAUDE.md` per proiect).
|
||||
- Cache-ul text e regenerabil, în afara arborelui SVN/git al proiectului — poate fi șters oricând.
|
||||
- Conversia **nu** necesită IDE-ul VFP deschis (folosește EXE-ul compilat).
|
||||
- Vezi și [conventie_encoding_cp1252.md](conventie_encoding_cp1252.md) — capcană de encoding la
|
||||
editarea `.sc2`/`.vc2` (nu doar la căutare).
|
||||
|
||||
35
docs/cercetare/ff_view_articole_vanzare.sql
Normal file
35
docs/cercetare/ff_view_articole_vanzare.sql
Normal file
@@ -0,0 +1,35 @@
|
||||
-- 08.08.2026 Marius Mutu
|
||||
-- VVANZARI_ARTICOLE: liniile unei vanzari (VANZARI_DETALII) cu denumirea articolului, a gestiunii
|
||||
-- si a valutei, pentru gridul de articole din formularul de modificare a notei. Valori brute, fara
|
||||
-- conversie valutara si fara calcule - editarea scrie inapoi exact ce a citit. Filtrul STERS ramane
|
||||
-- pe seama apelantului, ca la VACT_TOT / VRUL_TOT / VRUL_OBINV_TOT.
|
||||
|
||||
CREATE OR REPLACE VIEW VVANZARI_ARTICOLE AS
|
||||
select vd.id_vanzare,
|
||||
vd.id_vanzare_det,
|
||||
vd.id_articol,
|
||||
vd.cantitate,
|
||||
vd.pret,
|
||||
vd.pret_cu_tva,
|
||||
vd.proc_tvav,
|
||||
vd.discount_unitar,
|
||||
vd.id_gestiune,
|
||||
vd.cont,
|
||||
vd.id_valuta,
|
||||
vd.id_jtva_coloana,
|
||||
vd.serie,
|
||||
vd.explicatie,
|
||||
vd.taxcode,
|
||||
vd.lot,
|
||||
vd.sters,
|
||||
na.denumire,
|
||||
na.codmat,
|
||||
ng.nume_gestiune,
|
||||
nv.nume_val
|
||||
from vanzari_detalii vd
|
||||
left join nom_articole na on na.id_articol = vd.id_articol
|
||||
left join nom_gestiuni ng on ng.id_gestiune = vd.id_gestiune
|
||||
left join nom_valute nv on nv.id_valuta = vd.id_valuta;
|
||||
|
||||
exec pack_migrare.UpdateVersiune('ff_2026_08_08_01_COMUN_VVANZARI_ARTICOLE');
|
||||
commit;
|
||||
127
docs/cercetare/handoff_watchdog_vfp.md
Normal file
127
docs/cercetare/handoff_watchdog_vfp.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Handoff — watchdog VFP + bisectie blocaj "View Parameter" gnAn
|
||||
|
||||
Predare la peste 310k context (Regula zero). **Doar stare, fara analize noi.** Raport analitic
|
||||
complet (dovezi, log-uri, discutie): `docs\cercetare\rec_watchdog_vfp.md`.
|
||||
|
||||
## 1. Inventar livrabile, cu fisier:linie
|
||||
|
||||
**Utilitar**: `D:\ROA\ROAFACTURARE\COMUN\utile\Teste\watchdog_vfp.ps1`. Linia de comanda completa:
|
||||
|
||||
```
|
||||
powershell -ExecutionPolicy Bypass -File "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\watchdog_vfp.ps1" -Script "<cale.prg>" -TimeoutSec 90 -AutoDismiss -MaxDialogs 10
|
||||
```
|
||||
|
||||
Lanseaza `vfp9.exe -A -T "<script>"`, detecteaza orice fereastra noua diferita de
|
||||
`Process.MainWindowHandle`, o captureaza (PNG + `WM_GETTEXT` pe titlu si controale copil) in
|
||||
`<folderul scriptului>\watchdog_out\`, si cu `-AutoDismiss` incearca s-o inchida STRICT prin mesaje
|
||||
Windows tintite pe handle (`BM_CLICK` pe buton Cancel/Anulare -> `WM_COMMAND IDCANCEL` ->
|
||||
`WM_KEYDOWN`/`WM_KEYUP` ca mesaj -> `WM_CLOSE`) - **FARA input real** (vezi sectiunea 3). Omoara
|
||||
procesul mereu la iesire (`finally`).
|
||||
|
||||
**Fisiere de test noi**:
|
||||
- `COMUN\utile\Teste\watchdog_selftest.prg` - caz banal de validare (MESSAGEBOX), folosit doar ca
|
||||
sa confirme ca watchdog-ul detecteaza/captureaza/dismite corect, inainte de cazul real.
|
||||
- `COMUN\utile\Teste\editare_factura\test_repro_izolat_gnan.prg` - experimentul B (izolat): DOAR
|
||||
`test_init_env_auto` + `update_jtva_coloane("", "crsJtvaTemp", 6)`, fara nimic din S4. NU
|
||||
reproduce blocajul - dovada ca `update_jtva_coloane`/`updateserver.prg` sunt nevinovate.
|
||||
|
||||
**Fisier de test modificat**: `COMUN\utile\Teste\editare_factura\test_page3_articole.prg`:
|
||||
- linia 176: `update_jtva_coloane("", "crsJtvaTemp", 6)` (parametrul schimbat din `0` in `6` -
|
||||
necesar pentru indexul `id_jtva` cerut de `Column63.ControlSource` din `omodificari.vc2:9199`;
|
||||
independent de defectul principal, fix cunoscut deja din `date_test_nnir.md`);
|
||||
- `PROCEDURE bisect_log_gnan` (noua, la coada fisierului, ~linia 236) + apeluri `DO bisect_log_gnan
|
||||
WITH <tag>, lcLog` inserate: in programul principal intre fiecare apel de nivel superior, si ca
|
||||
PRIMA linie in interiorul fiecarei proceduri (`verifica_vanzare_nota`, `verifica_coliziune_cod`,
|
||||
`verifica_pagecount_form`) - infrastructura de bisectie, ramasa in cod ca dovada;
|
||||
- **liniile 37, 39, 50 - remediul APLICAT DE TEAM-LEAD** (nu de mine, sub pragul lui de editare
|
||||
directa): `gnAn`/`gnLuna` parantezate - `(gnAn)`, `(gnLuna)` - in apelurile `DO verifica_vanzare_nota
|
||||
WITH ...` (x2) si `DO verifica_pagecount_form WITH ...` (primul), cu comentariu explicativ deasupra
|
||||
primei aparitii (liniile 34-36).
|
||||
|
||||
**Log-uri si capturi**: `test_page3_articole_log.txt` (log-ul aplicatiei, contine liniile `[BISECT]`),
|
||||
`watchdog_out\*.png` + `watchdog_out\*_watchdog.log` (capturi + jurnal watchdog, per fisier de test),
|
||||
toate in `COMUN\utile\Teste\editare_factura\`.
|
||||
|
||||
## 2. Ce e terminat, ce nu
|
||||
|
||||
**Terminat**:
|
||||
- Watchdog-ul: scris, testat pe caz banal, testat pe cazul real, corectat (heuristica de fereastra
|
||||
principala, bug de indexare PowerShell pe array cu 1 element, input real scos complet).
|
||||
- Bisectia: COMPLETA, cauza CONFIRMATA cu date brute (nu deductie) - vezi sectiunea 4.
|
||||
- Remediul: APLICAT de team-lead (liniile 37/39/50).
|
||||
|
||||
**Neterminat**: remediul NU a fost re-testat dupa aplicare. Ultima rulare a suitei (a mea) a fost
|
||||
INAINTE de remediul team-lead-ului. Team-lead ruleaza el insusi suita, separat - **eu nu mai rulez
|
||||
nimic** (interdictie explicita primita).
|
||||
|
||||
## 3. Stare fisiere - write-back
|
||||
|
||||
**Toate fisierele atinse in aceasta sesiune sunt `.prg`/`.ps1` (text simplu)** - NU exista
|
||||
`.vc2`/`.sc2`/`.vcx`/`.vct` atinse, deci **NU exista niciun write-back nefacut**.
|
||||
|
||||
Confirmare explicita: `COMUN\clase\omodificari.vc2/.vcx/.vct` si `COMUN\programe\updateserver.prg`
|
||||
sunt **NEATINSE** in aceasta sesiune (nici de mine, nici - din cate stiu - de altcineva). Fara
|
||||
commit git/svn facut sau initiat.
|
||||
|
||||
## 4. Ce s-a stabilit deja - NU relua
|
||||
|
||||
- **Cauza CONFIRMATA, nu ipoteza**: `test_page3_articole.prg` (inainte de remediu) trecea
|
||||
`gnAn`/`gnLuna` NEPARANTEZAT in `DO...WITH` (liniile 34, 36, 47 - numerotare dinainte de remediu).
|
||||
`DO proc WITH var` paseaza variabile de memorie BY REFERENCE implicit in VFP; `LPARAMETERS`
|
||||
primitor devine alias direct pe storage-ul original, iar numele original (`gnAn`) devine
|
||||
inaccesibil (`TYPE()='U'`) STRICT pe durata acelui apel, revenind valid imediat dupa `RETURN`.
|
||||
Confirmat simetric pe 3 apeluri afectate vs 2 neafectate (vezi tabelul din `rec_watchdog_vfp.md`
|
||||
sectiunea 5).
|
||||
- **`updateserver.prg`/`update_jtva_coloane` sunt nevinovate** - experimentul B (izolat, fara nimic
|
||||
din S4) NU reproduce; functia merge perfect cand `gnAn` e vizibil normal.
|
||||
- **`gnAn` NU e eliberata niciodata** - ramane valida (`TYPE()='N'`, 2026) la FIECARE checkpoint din
|
||||
scope-ul PRINCIPAL, fara exceptie. Nu exista `CLEAR ALL`/`CLEAR MEMORY`/`RELEASE ALL EXTENDED` pe
|
||||
lantul executat.
|
||||
- **Nu e coliziune de nume in corpul procedurii**: `verifica_pagecount_form` NU are `gnAn` in
|
||||
`LOCAL` (linia ei 148/159), si NU exista `PRIVATE gnAn`/`LOCAL gnAn` nicaieri in `COMUN\programe`.
|
||||
Umbrirea vine din SINTAXA APELULUI (`DO...WITH` neparantezat), nu din declaratiile callee-ului.
|
||||
- **Handler-ul de eroare** (`test_error_handler`/`ON ERROR`) doar logheaza (`STRTOFILE`) si continua
|
||||
- nu ascunde nimic, util pentru diagnostic.
|
||||
- **Incidentul de focus**: ESC-ul trimis de o versiune veche a watchdog-ului (cu `SetForegroundWindow`
|
||||
+ `keybd_event`, SCOASA complet acum) a aterizat de fapt in PROPRIUL nostru proces de test, NU in
|
||||
sesiunea utilizatorului - dar mecanismul tot nu are tinta si regula "fara input real" ramane
|
||||
obligatorie indiferent (documentat in `rec_watchdog_vfp.md` sectiunea 1, corectat acolo dupa o
|
||||
formulare initiala gresita).
|
||||
|
||||
## 5. Ce e interzis
|
||||
|
||||
- Input real de tastatura/mouse in watchdog (`keybd_event`, `SetForegroundWindow`, `SendInput`,
|
||||
`mouse_event`) - masina e PARTAJATA. Deja scos din cod, verificat cu grep (zero hit-uri de cod,
|
||||
doar comentarii care explica interdictia).
|
||||
- Atingerea `COMUN\clase\omodificari.vc2/.vcx/.vct` si `COMUN\programe\updateserver.prg`.
|
||||
- Commit git/svn.
|
||||
- **Eu nu mai rulez suita** - team-lead o ruleaza separat dupa remediul lui.
|
||||
|
||||
## 6. Capcane de mediu platite in aceasta sesiune
|
||||
|
||||
- **Heuristica "prima fereastra vazuta = principala" e o cursa pierduta**: un dialog poate aparea in
|
||||
aceeasi fractiune de secunda cu fereastra principala. Solutia corecta: `Process.MainWindowHandle`
|
||||
(.NET), NU ordinea de aparitie si NU numele clasei (VFP foloseste clase `vfp9...` si pentru shell,
|
||||
si pentru dialogurile proprii - `vfp99400000` vs `vfp994000002`).
|
||||
- **Dialogurile proprii VFP (ex. "View Parameter") sunt owner-drawn** - `EnumChildWindows` intoarce
|
||||
ZERO controale copil (butoanele sunt desenate, nu HWND-uri reale). `BM_CLICK` e imposibil pentru
|
||||
ele; chiar si `WM_CLOSE` poate "reusi" aparent (`IsWindow` -> fals) FARA sa deblocheze de fapt
|
||||
motorul VFP din spate (SQLEXEC ramas agatat, fara linie noua in log, pana la timeout) - un fals
|
||||
"succes" de retinut daca cineva reia mecanismul de dismiss.
|
||||
- **Bug PowerShell subtil**: un `List[string]` cu UN SINGUR element e "descompus" de PowerShell la
|
||||
scalar string simplu la `return` din functie (fara `,` unar) - indexarea ulterioara `$x[0]` citeste
|
||||
atunci primul CARACTER, nu primul element. Prins la dump-ul de text al dialogului "View Parameter"
|
||||
(fara controale copil = un singur element in listă). Fix: `return , $lista.ToArray()`.
|
||||
- **`.fxp` vechi blocat**: sterge intotdeauna `.fxp`-ul inainte de fiecare rulare (watchdog-ul o face
|
||||
singur) - altfel VFP ruleaza tacut codul vechi compilat.
|
||||
- **Bisectia**: `TRANSFORM(gnAn)` pe o variabila `TYPE()='U'` ARUNCA eroare catchabila ("Variable
|
||||
'GNAN' is not found") - helper-ul `bisect_log_gnan` verifica `TYPE()<>'U'` INAINTE de a apela
|
||||
`TRANSFORM()`, ca sa nu produca o eroare noua care ar fi intrerupt bisectia la primul checkpoint
|
||||
"gol".
|
||||
|
||||
## Confirmare finala
|
||||
|
||||
**PID 16548 nu mai exista** (verificat cu `Get-Process -Id 16548` - inexistent la momentul acestui
|
||||
handoff) si **niciun `vfp9.exe` nu ruleaza** (verificat cu `Get-Process vfp9` - lista goala). Nimic
|
||||
in stare periculoasa: fara editare pe jumatate, fara cursor/tranzactie Oracle deschisa (doar
|
||||
citiri), fara fisier binar atins. Sesiunea se opreste aici.
|
||||
210
docs/cercetare/import_roris_roaacnpro.md
Normal file
210
docs/cercetare/import_roris_roaacnpro.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# Anatomia butonului "Import Roris & Contracte" (ROAACNPRO)
|
||||
|
||||
Cercetare read-only in `D:\ROA\ROAACNPRO`, ca model pentru un buton generic
|
||||
"importa articole din sursa" intr-un formular de facturare unificat in ROAFACTURARE.
|
||||
Nicio editare de fisiere, niciun `git_sync.ps1`/`txt2vcx.ps1`, niciun commit — doar investigatie.
|
||||
|
||||
## 1. Localizare
|
||||
|
||||
**Concluzie**: Butonul e `cmdImport` (clasa `cmd_executa`) pe formularul `frm_factura`, definit in
|
||||
`Clase\oacnpro.vc2`. Nu are `Click` propriu — mosteneste `Click` din clasa de baza a butoanelor,
|
||||
care ruleaza metoda numita in proprietatea `caction`; `cmdImport` nu suprascrie `caction`, deci
|
||||
ramane valoarea implicita `do_executa` mostenita de la clasa `cmd_executa`
|
||||
(`COMUN\clase\cmd_butoane.vc2:474`). Codul efectiv e in `PROCEDURE do_executa` a formularului
|
||||
`frm_factura`.
|
||||
|
||||
**Dovezi**:
|
||||
- `Clase\oacnpro.vc2:6894-6905` — definirea controlului:
|
||||
```
|
||||
ADD OBJECT 'cmdImport' AS cmd_executa WITH ... Caption = "\<Import Roris & Contracte", ... Left = 597, Top = 65, Width = 169
|
||||
```
|
||||
- `COMUN\clase\cmd_butoane.vc2:474` — `caction = do_executa` (mostenit de `cmd_executa`).
|
||||
- `COMUN\clase\_cmd_base.vc2:120-159` — `PROCEDURE Click` a clasei de baza: construieste
|
||||
`lcCommand = [this.Parent.] + lcAction + ...` si il executa cu macro (`&lcCommand`).
|
||||
- `Clase\oacnpro.vc2:7814-7836` — `PROCEDURE do_executa` a lui `frm_factura` (clasa incepe la
|
||||
`oacnpro.vc2:6398 DEFINE CLASS frm_factura`, se termina la `8383`).
|
||||
|
||||
## 2. Preconditii
|
||||
|
||||
**Concluzie**: Butonul e activ doar daca (a) factura nu e inca salvata (`llFacturaEditabila`) si
|
||||
(b) tipul facturii (`poDate.cTip`, ales din `cboTip`) e unul din
|
||||
`TRANZIT, CHEIAJ, CHIRII, APA, PENALITATI`. In plus, la Click, `do_executa` verifica separat ca a
|
||||
fost ales clientul.
|
||||
|
||||
**Dovezi**:
|
||||
- `Clase\oacnpro.vc2:8117-8145`:
|
||||
```
|
||||
llFacturaEditabila = !This.lFacturaSalvata
|
||||
llRorisSauContracte = INLIST(poDate.cTip, 'TRANZIT', 'CHEIAJ', 'CHIRII', 'APA', 'PENALITATI') && butonul import RORIS&Contracte este activ doar pentru RORIS sau contracte
|
||||
...
|
||||
.cmdImport.Enabled = m.llFacturaEditabila and m.llRorisSauContracte
|
||||
```
|
||||
- `Clase\oacnpro.vc2:7820-7823`:
|
||||
```
|
||||
IF EMPTY(NVL(this.nIdClient,0))
|
||||
AMESSAGEBOX('Alegeti clientul!',0+48,_screen.Caption)
|
||||
RETURN
|
||||
ENDIF
|
||||
```
|
||||
- Fara client ales, butonul e vizibil/activ dar Click-ul se opreste cu acest mesaj.
|
||||
|
||||
## 3. Ce face efectiv
|
||||
|
||||
**Concluzie**: `do_executa` -> `factura_import()` (`Programe\proceduri_acnpro.prg:3151`) ramifica
|
||||
dupa `poDate.cTip`:
|
||||
- TRANZIT/CHEIAJ: `vizualizare_tranzit()` -> deschide dialogul `frm_tranzit` (selectie convoaie din
|
||||
vederea Oracle `ips_vvoyages`) -> la confirmare, `calcul_tranzit()`/`calcul_cheiaj()` interogheaza
|
||||
direct (SELECT-uri simple, nu pachete PL/SQL) tabelele/vederile `ips_vvoyage_members_calcul`,
|
||||
`ips_vvoyage_locks`, apoi deschide un al doilea dialog de editare tarife (`frm_calcul_tranzit`).
|
||||
- CHIRII/APA: `vizualizare_contract()` -> `calcul_contract()` -> SELECT din vederea
|
||||
`vctr_articole2` (articole de contract) -> dialog `frm_calcul_contract`.
|
||||
- PENALITATI: `vizualizare_penalitati()` -> `frm_penalitati` cu cursorul `crsCalculPenalitati`
|
||||
calculat in VFP din vederile `vanzari`/`ireg_parteneri`/`penalitati`.
|
||||
|
||||
Dupa confirmarea dialogului (validat prin variabila globala `gnButon = 1`, standard framework
|
||||
pentru formulare modale), se apeleaza `make_factura_tranzit` / `make_factura_cheiaj` /
|
||||
`make_factura_contracte` / `make_factura_penalitati`, care insereaza direct in `crsFactura`.
|
||||
|
||||
**Important**: nicio procedura Oracle stocata (`pack_*`) nu e apelata in etapa de import — acestea
|
||||
(`pack_facturare.*`, `pack_acn.salveaza_regdoc`, `pack_contafin.*`) sunt apelate abia la
|
||||
**salvarea** finala a facturii (`factura_salvare_db`, `Programe\proceduri_acnpro.prg:3290+`), nu
|
||||
la import.
|
||||
|
||||
**Dovezi**:
|
||||
- `Programe\proceduri_acnpro.prg:3151-3212` (`Procedure factura_import`), `740-771`
|
||||
(`calcul_tranzit`, sursa `ips_vvoyage_members_calcul`), `1127-1161` (`calcul_contract`, sursa
|
||||
`vctr_articole2`).
|
||||
- `Programe\proceduri_acnpro.prg:939-943`:
|
||||
`loFrmTranzit = Crea("frm_calcul_tranzit", ...); loFrmTranzit.Show(1); llSucces = (m.gnButon = 1)`.
|
||||
- `Programe\proceduri_acnpro.prg:3331-3467` — apelurile `pack_facturare.*`/`pack_acn.salveaza_regdoc`
|
||||
sunt in `factura_salvare_db`, nu in `factura_import`.
|
||||
|
||||
## 4. Cum populeaza factura
|
||||
|
||||
**Concluzie**: Scrie **direct** in cursorul de articole al facturii, `crsFactura`, prin
|
||||
`INSERT INTO crsFactura(...)` in fiecare `make_factura_*` — nu trece prin vreo metoda generica
|
||||
"adauga articol" a formularului (exista o metoda separata `do_adauga_articol` pentru adaugare
|
||||
manuala de linie, dar importul n-o foloseste). Liniile se **adauga** peste cele existente (nu
|
||||
sterge/inlocuieste `crsFactura` inainte). Protectia la dublu-import e partiala:
|
||||
- dupa un import reusit, `This.cmdImport.Enabled = .F.` dezactiveaza butonul (nu se mai poate
|
||||
importa a doua oara in aceeasi sesiune de editare a facturii);
|
||||
- pentru TRANZIT/CHEIAJ exista un avertisment (nu blocaj) daca pe convoaiele alese exista deja
|
||||
facturi (`ips_vvoyages_vanzari.numar_act IS NOT NULL`) — utilizatorul poate continua oricum.
|
||||
|
||||
**Dovezi**:
|
||||
- `Clase\oacnpro.vc2:7827-7834`:
|
||||
```
|
||||
llSucces = factura_import(m.tlImportCalculat)
|
||||
IF m.llSucces
|
||||
This.cmdImport.Enabled = .F. && nu mai import altceva
|
||||
This.chkIntern.Enabled = .F.
|
||||
This.ActiveazaSalvare()
|
||||
...
|
||||
```
|
||||
- `Programe\proceduri_acnpro.prg:3601` (TRANZIT) / `3677-3678` (CHEIAJ) / `3764-3765`
|
||||
(CHIRII/APA): `Insert Into crsFactura(nrcrt, id_articol, denumire, ...)`.
|
||||
- `Clase\oacnpro.vc2:14915-14930` — avertisment dublu-import in `frm_tranzit.do_executa`:
|
||||
```
|
||||
SELECT numar_act, data_act, client FROM ips_vvoyages_vanzari WHERE vye_id in (...) AND numar_act is NOT null ...
|
||||
IF RECCOUNT('cFacturiTranzitTemp') > 0
|
||||
lcMesaj = 'Atentie! Exista facturi pe tranzitele alese!' + CHR(13)+CHR(10) + ...
|
||||
AMESSAGEBOX(m.lcMesaj,0+48,_screen.Caption)
|
||||
ENDIF
|
||||
```
|
||||
(mesaj informativ, apoi continua oricum cu `calcul_tranzit`/`calcul_cheiaj`).
|
||||
|
||||
## 5. Feedback catre utilizator
|
||||
|
||||
**Concluzie**: Mesaje punctuale prin `AMESSAGEBOX`, nu un sistem unitar de raportare:
|
||||
- Client lipsa: `'Alegeti clientul!'` (`oacnpro.vc2:7821`).
|
||||
- Convoi/liniile de import lipsa dupa dialog: `'Alegeti un convoi!'` in `make_factura_tranzit`
|
||||
daca `poDate.uuid` (id-urile alese) e gol (`proceduri_acnpro.prg:3530`); analog pentru
|
||||
CHIRII/APA prin `factura_salvare` (`'Alegeti convoiul'`/`'Adaugati prestatii'`,
|
||||
`proceduri_acnpro.prg:3221`, dar aceasta e verificare la *salvare*, nu la import).
|
||||
- Facturi deja existente pe convoaiele alese: avertisment neblocant (vezi punctul 4).
|
||||
- Zero rezultate in dialogul de selectie (`frm_tranzit`/`frm_calcul_contract`): niciun mesaj
|
||||
explicit gasit — grila ramane goala, iar la `Calculare`/`Terminat` fara nimic bifat `lcVyeIds`
|
||||
ramane vid si `IF !EMPTY(m.lcVyeIds)` (`oacnpro.vc2:14912`) sare peste tot calculul, fara mesaj
|
||||
catre utilizator (comportament implicit: butonul pare sa nu faca nimic).
|
||||
- Eroare Oracle: nu exista tratare `TRY/CATCH` explicita in `factura_import`/`calcul_tranzit`/
|
||||
`make_factura_*`; erorile SQL se propaga prin returul `.F.` al lui
|
||||
`goExecutor.oExecuta`/`oSelecteaza2Value`, iar afisarea erorii tine de comportamentul standard
|
||||
al `goExecutor` (framework comun, neexaminat in detaliu aici).
|
||||
|
||||
**Dovezi**: citatele de mai sus; pentru "zero rezultate fara mesaj" — `Clase\oacnpro.vc2:14898-14943`.
|
||||
|
||||
## 6. Selectivitate
|
||||
|
||||
**Concluzie**: Da, exista dialoage intermediare cu selectie, diferite pe tip:
|
||||
- **TRANZIT/CHEIAJ**: `frm_tranzit` (`oacnpro.vc2:14492-15003`) — grid `grdTranzit` cu coloane
|
||||
`Declaratia`, `Data decl.`, `Convoi`, `Origin`, `Destinatie` si o coloana checkbox `cAles`
|
||||
(`ControlSource='crsConvoaie.ales'`), plus criterii de cautare (`Cb_tx_cautare1`,
|
||||
`But_start_criterii1`/`But_reset_criterii1`) si buton `cmdCalculeaza` ("Calculare Tarife").
|
||||
Utilizatorul bifeaza unul sau mai multe convoaie; daca nu bifeaza niciunul, se ia randul curent
|
||||
(`lcVyeId` din `crsConvoaie` la pozitia curenta). Dupa `Calculare Tarife`, se deschide **al
|
||||
doilea nivel** — `frm_calcul_tranzit`/`frm_calcul_cheiaj` — pentru editarea/confirmarea
|
||||
tarifelor calculate, inainte de a reveni in factura.
|
||||
- **CHIRII/APA**: `calcul_contract()` deschide `frm_calcul_contract` cu cursorul
|
||||
`crsArticoleContract` (articol, perioada, um, pret, cantitate, valoare, valuta, locatie) din
|
||||
vederea `vctr_articole2` filtrata pe `id_ctr` — practic toate articolele contractului curent,
|
||||
editabile in acel dialog.
|
||||
- **PENALITATI**: `frm_penalitati` cu grid `grdPenalitati` (`crsCalculPenalitati`), coloane
|
||||
vizibile precum `cNrDoc`, `cSuma` ("Sold restant" in modul evaluare), `cDataDoc`.
|
||||
|
||||
Deci nu e un "importa tot" fara interventie — e mereu mediat de un dialog de vizualizare/calcul/
|
||||
confirmare (`gnButon = 1` = utilizatorul a confirmat).
|
||||
|
||||
**Dovezi**: `Clase\oacnpro.vc2:14500-14515` (obiecte grid + `cAles`), `14801`
|
||||
(`ControlSource='crsConvoaie.ales'`), `14594-14601` (`cmdCalculeaza`);
|
||||
`Programe\proceduri_acnpro.prg:1137-1153` (`crsArticoleContract` din `vctr_articole2`);
|
||||
`Programe\proceduri_acnpro.prg:545-555` (`frm_penalitati`, `grdPenalitati.cSuma`, `.cNrDoc`,
|
||||
`.cDataDoc`).
|
||||
|
||||
## 7. Butoanele vecine
|
||||
|
||||
**Concluzie**: Pe `frm_factura`, `cmdImport` e plasat in zona antetului facturii
|
||||
(`Left=597, Top=65`), langa `cboTip` (`Left=507, Top=67` — combo cu tipul facturii) si
|
||||
`chkIntern` (`Left=412, Top=70`) — nu langa bara principala de butoane. Bara principala de sus
|
||||
(`Top=0`) contine, in ordinea `Left`: `but_factura_noua` ("Nou", `Left=688`), `But_salveaza1`
|
||||
("Salveaza", `Left=719`), `But_renunt1` ("Renunta", `Left=749`). Separat, langa grila
|
||||
`grdFactura`, exista butoane de linie (`Top=120`): `But_nou1` ("Adauga linie", `Left=707`) si
|
||||
`But_sterge1` ("Sterge linie", `Left=737`). Mai sunt `but_cautare_client`/`but_cautare_beneficiar`
|
||||
(lupa cautare partener, langa campurile de client/beneficiar).
|
||||
|
||||
**Dovezi**: `Clase\oacnpro.vc2:6779-6818` (definitiile `but_factura_noua`, `But_nou1`,
|
||||
`But_renunt1`, `But_salveaza1`, `But_sterge1` cu `Left`/`Top`), `6836-6851` (`cboTip`),
|
||||
`6853-6863` (`chkIntern`), `6894-6905` (`cmdImport`).
|
||||
|
||||
## Ce e transferabil in ROAFACTURARE
|
||||
|
||||
Tiparul general merita copiat ca **model de arhitectura pentru un buton generic "importa
|
||||
articole din sursa"**:
|
||||
1. Buton activ conditionat de (a) factura editabila (nesalvata) si (b) tip de document care are o
|
||||
sursa de import — exact ca `llFacturaEditabila and llRorisSauContracte`.
|
||||
2. O metoda de intrare unica (`do_executa`/`factura_import`) care ramifica dupa tipul documentului
|
||||
catre functii specializate de "vizualizare/selectie" — fiecare deschide un dialog modal de
|
||||
selectie (grid cu coloana checkbox `ales`, criterii de cautare), returneaza succes/esec prin
|
||||
variabila globala tip `gnButon = 1`.
|
||||
3. Populare prin `INSERT INTO <cursor_articole>` direct, aditiv (nu sterge liniile existente), cu
|
||||
dezactivarea butonului dupa import reusit ca protectie minimala la dublu-import — plus
|
||||
(optional) un avertisment neblocant daca sursa a mai fost deja folosita in alta factura.
|
||||
4. Separarea neta intre etapa de **calcul/import** (SELECT-uri simple pe vederi Oracle, fara
|
||||
proceduri stocate) si etapa de **salvare** (unde intra pachetele PL/SQL) — util ca principiu:
|
||||
importul nu trebuie sa scrie definitiv in baza, doar sa populeze cursorul local.
|
||||
|
||||
Ce e strict specific ACN/RORIS si **nu** se transfera: sursele de date (`ips_vvoyages`,
|
||||
`ips_voyage_members_vanzari`, `ips_vberthing_details_vanzari`, `vctr_articole2`), logica de calcul
|
||||
tarife/ecluzari/porturi, formularele `frm_tranzit`/`frm_calcul_tranzit`/`frm_calcul_contract`/
|
||||
`frm_penalitati` ca atare, si valorile `poDate.cTip` (`TRANZIT/CHEIAJ/CHIRII/APA/PENALITATI`).
|
||||
|
||||
## Necunoscute ramase
|
||||
|
||||
- Comportamentul exact al `goExecutor.oExecuta`/`oSelecteaza2Value` la eroare Oracle (mesaj
|
||||
afisat, retry, log) — n-a fost verificat in profunzime (functie framework comun).
|
||||
- Continutul complet al dialogului `frm_calcul_tranzit`/`frm_calcul_cheiaj` (al doilea nivel,
|
||||
editare tarife) — am confirmat doar ca exista si ca `gnButon=1` marcheaza confirmarea, dar nu am
|
||||
detaliat coloanele/campurile lui.
|
||||
- Detaliile `frm_calcul_contract` (butoane, posibilitate de deselectare articole individuale) nu
|
||||
au fost citite integral — doar sursa cursorului.
|
||||
- Nu am verificat daca exista vreo validare suplimentara de "acelasi convoi importat de doua ori
|
||||
in aceeasi factura" dincolo de avertismentul cross-factura mentionat la punctul 4.
|
||||
220
docs/cercetare/rec_consumatori_vanzari.md
Normal file
220
docs/cercetare/rec_consumatori_vanzari.md
Normal file
@@ -0,0 +1,220 @@
|
||||
# Inventar consumatori `VANZARI.AVIZE`/`CURS`/`ID_VALUTA`/`MULTIPLICATOR` in suita ROA
|
||||
|
||||
Cercetare STRICT de citire (fara modificari de cod, fara DDL, fara conexiuni DB, fara rulare de
|
||||
conversii noi `vcx2txt.ps1`/`git_sync.ps1`) — masoara riscul de comportament schimbat dupa
|
||||
corectiile S4 (AVIZE, WHERE lipsa) si S8/curs (garda `nin_valuta`) aplicate in `PACK_FACTURARE`
|
||||
(vezi `rec_s4_aplicare.md`). Executata cu 3 subagenti in paralel: (a) ROAFACTURARE+COMUN, (b) cele
|
||||
8 produse cu cache text deja generat, (c) restul suitei (~56 directoare).
|
||||
|
||||
## RISC REAL
|
||||
|
||||
**1. Referinta la aviz dispare de pe factura retiparita (tip=4).**
|
||||
`COMUN\programe\oproceduri_facturare.prg` (`listeaza_formular`, ~:1125/:1189/:1265) si dublura ei
|
||||
`COMUN\clase\ofacturare_comun.vc2` (`frm_facturi.do_listeaza_formular`, ~:4103/:4204) — cod
|
||||
partajat, prezent in tot ecosistemul ROA*. Construiesc `crsFacturaListare` din `FACT_VFACTURI2`
|
||||
(coloana `altele` = alias pentru `vanzari.avize` cand `tip in (4,24,8,9)`), apoi
|
||||
`poDate.descriere = Alltrim(altele)` specific pentru `tip=4` ("factura din aviz"). `poDate.descriere`
|
||||
ajunge pe formularul tiparit ca referinta "nr. aviz" (layout exact in `.frx`, neconvertit — vezi
|
||||
gap mai jos). **Ce se schimba**: la retiparirea/relistarea unei facturi `tip=4` mai vechi, unde
|
||||
`vanzari.avize` era populat gresit inainte (smearat de UPDATE-ul fara WHERE) si acum e gol pentru
|
||||
majoritatea facturilor, referinta la aviz dispare vizibil de pe document. E in calea de reprint,
|
||||
nu de emitere — deci afecteaza utilizatorul la orice reeditare/retiparire ulterioara corectiei.
|
||||
|
||||
**2. Nota "Curs: X RON/valuta" pe factura electronica/PDF, generata fara verificare `in_valuta`.**
|
||||
`xmlefactura.prg` (COMUN partajat, cod identic — verificat prin hash — in ROAEFACTURA, ROASITFIN,
|
||||
ROACONIMPORT, ROAPRINT, ROAPRODUCTIE, ROACONT/OUTPUT, si prezent si in ROAFACTURARE/COMUN):
|
||||
```
|
||||
IF !EMPTY(NVL(loDate.curs,0)) AND ATC('curs', m.lcTextAditional) = 0
|
||||
lcTextAditional = ... + "Curs: " + ALLTRIM(STR(loDate.curs,10,4)) + " RON/" + ... loDate.cValuta ...
|
||||
ENDIF
|
||||
```
|
||||
Conditia verifica doar `curs` nenul, nu si `loDate.in_valuta` (spre deosebire de blocul de cateva
|
||||
linii mai jos, `DocumentCurrencyCode`, care testeaza corect `in_valuta=1`). Inainte, facturile in
|
||||
LEI aveau deja `curs` populat gresit (bug), deci nota aparea eronat, dar cu o valoare "plauzibila".
|
||||
**Ce se schimba**: dupa corectie, `curs=1` pe facturile in lei — `!EMPTY(1)` tot trece, deci nota
|
||||
tot apare, dar acum arata constant `"Curs: 1.0000 RON/"` cu sufix de valuta gol (`id_valuta=0`).
|
||||
Vizibil pe fiecare factura/aviz in lei exportata ca e-factura sau tiparita, in toate produsele de
|
||||
mai sus.
|
||||
|
||||
## RISC POSIBIL
|
||||
|
||||
3. **`ofacturare_comun.vc2:4156-4157`** (si dublura `oproceduri_facturare.prg:1225-1226`): dupa
|
||||
blocul `If poDate.in_valuta = 1 ... Else ... Endif`, `poDate.Curs`/`poDate.multiplicator` sunt
|
||||
suprascrise necondiționat din valorile citite din view. Calculul de discount e corect protejat
|
||||
de `in_valuta=1`, dar nu s-a putut confirma daca FRX-ul (neconvertit) afiseaza aceste campuri
|
||||
necondiționat de `in_valuta`. De verificat in layout-ul tiparit.
|
||||
4. **`vizualizare_facturi2` (`oproceduri_facturare.prg:431-479`)**: grid-ul de cautare/listare
|
||||
facturi expune coloanele `altele`, `curs`, `multiplicator`, `valuta`, `id_valuta`, `nume_val`
|
||||
direct din `FACT_VFACTURI2`. Nu s-a putut confirma legarea la `ControlSource` in `.scx`
|
||||
(neconvertit) — daca vreuna e legata vizibil intr-un grid, utilizatorii ar vedea coloane
|
||||
goale/"1" unde inainte vedeau valori (gresite).
|
||||
5. **ROAACNPRO** `Programe\proceduri_acnpro.prg:1180-1229`, `calcul_penalitati` (calea activa):
|
||||
`Select v.Curs, v.id_Valuta ... left join vnom_valute vl on v.id_valuta = vl.id_valuta From
|
||||
vanzari v`, afisat probabil intr-un grid de review inainte de generarea facturilor de
|
||||
penalizare. Calculul numeric al penalitatii NU foloseste `curs` (confirmat), deci fara risc de
|
||||
calcul; ramane risc de **afisare**: `id_valuta=0` ar putea sa nu se potriveasca in
|
||||
`left join vnom_valute` (tabela de valute proprie ACNPRO, distincta de `NOM_VALUTE`), lasand
|
||||
coloana `valuta` goala. Nu s-a putut confirma daca `vnom_valute` are un rand pentru
|
||||
`id_valuta=0` (spre deosebire de `NOM_VALUTE`, unde existenta randului `id_valuta=0` a fost deja
|
||||
confirmata in `rec_s4_aplicare.md`, punctul 3 din sectiunea S8/curs — deci pentru view-urile
|
||||
`FACT_VFACTURI*` din COMUN acest risc e deja exclus, ramane specific tabelei proprii ACNPRO).
|
||||
6. **ROAAUTO** `Programe\oproceduri_devize.prg:1486-1532`, `relisteaza_factura_deviz`: citeste
|
||||
`curs`/`multiplicator`/`altele` din `fact_vfacturi` la reafisarea unei facturi, dar cursorul se
|
||||
inchide imediat fara ca valorile sa fie propagate mai departe — risc redus, de reverificat doar
|
||||
daca un apelant viitor se bazeaza pe acelasi cursor.
|
||||
7. **`CONTAFIN2ORA\VFP2ORA\Programe\acn.prg:~1247-1319`** (unealta de migrare, nu produs curent de
|
||||
vanzare): scrie direct `curs`/`id_valuta`/`multiplicator` in `INSERT INTO VANZARI` +
|
||||
`MERGE INTO VANZARI_CURSURI`, cu propria regula de zero-ing independenta de `PACK_FACTURARE` —
|
||||
probabil neafectata functional, dar merita o verificare separata daca unealta mai e folosita
|
||||
activ.
|
||||
|
||||
## FARA RISC (rezumat, nu enumerate)
|
||||
|
||||
- **ROAFACTURARE+COMUN**: restul celor ~930 potriviri brute pentru `AVIZE`/`CURS`/`ID_VALUTA`/
|
||||
`MULTIPLICATOR`/`ALTELE` — module NIR/import, balante/parteneri/compensari, salarii, curs
|
||||
valutar BNR, sau citiri deja corect protejate de `in_valuta`/`tip_valuta`
|
||||
(`ofacturare.prg::listeaza_ofacturare` la emitere, `ofacturare_stoc.prg`, `anaf_efactura.prg` cu
|
||||
`decode(in_valuta,1,curs,1)`, `makexmlfacturaelectronica.prg` cu garda `mmoneda<>"RON"`). Niciun
|
||||
hit `.avize` (acces direct de camp) in afara celor doua raportate mai sus.
|
||||
- **ROACONT**: `Programe\saft_d406.prg` (declaratia fiscala D406, `oSalesInvoices`) — foloseste
|
||||
`DECODE(v.in_valuta, 0, 0, ...)` explicit, output SAF-T neschimbat de corectie. Restul hit-urilor
|
||||
pe tabele proprii (`ireg_parteneri`, `act`, `rul`) sau text necorelat.
|
||||
- **ROAACNPRO** (restul), **ROACONTRACTE**, **ROAGEST**, **ROAIMOB**, **ROAREGISTRATURA**,
|
||||
**ROASTART**: zero hit relevant legat de `VANZARI` in afara COMUN (verificat, nu doar negasit).
|
||||
- **~40 de produse din restul suitei** (ROAEFACTURA si variante, ROASITFIN, ROAPRINT,
|
||||
ROACONIMPORT, ROAPRODUCTIE, ROAHOTEL si variante, ROASAL, ROAMANAGER, ROADECL, ROAPRETURI,
|
||||
ROABAZA, ROAAPROV, ROADEVIZE, etc.): hit-uri pe "AVIZE" = conceptul de business "aviz de
|
||||
expeditie" (tip document), nu coloana; hit-uri "CURS"/"ID_VALUTA" pe alte tabele proprii sau in
|
||||
`oDateFactura` (populate de apelant, protejate de `in_valuta`). `COMUNROA` (depozitul central)
|
||||
contine doar scripturi de deployment, fara logica de facturare.
|
||||
|
||||
## Rezumat acoperire
|
||||
|
||||
- **ROAFACTURARE + COMUN local**: acoperire completa `.prg` + `.vc2`/`.sc2` via `vfp_symbols.ps1
|
||||
-CodeOnly` (index deja construit). **Gap**: 207 `.frx` si 30 `.mnx` fara `.fr2`/`.mn2` in cache —
|
||||
layout-ul efectiv tiparit (unde `poDate.descriere`/`Curs`/`cValuta` chiar apar pe hartie) nu e
|
||||
verificabil fara conversie (interzisa in acest task). Riscurile REAL #1/#2 si POSIBIL #3/#4
|
||||
depind partial de acest layout.
|
||||
- **8 produse cu cache text existent** (ROAACNPRO, ROAAUTO, ROACONT, ROACONTRACTE, ROAGEST,
|
||||
ROAIMOB, ROAREGISTRATURA, ROASTART): acoperire completa `.prg` + `.vc2`/`.sc2` via
|
||||
`vfp_symbols.ps1 -CodeOnly`. **Gap**: proprietati/metadata (`ControlSource` de grid legat direct
|
||||
de o coloana, fara linie de cod explicita) nu apar in `-CodeOnly` — dar un asemenea caz s-ar
|
||||
clasifica oricum FARA RISC (simpla afisare).
|
||||
- **Restul suitei** (~56 directoare, inclusiv `COMUNROA`): acoperire **doar** pe fisierele `.prg`
|
||||
(text simplu, nu necesita conversie); zero cache text pentru `.vcx`/`.scx` — **niciun cod din
|
||||
clase/formulare compilate al acestor produse nu a fost verificat**, conform interdictiei de a
|
||||
genera cache nou. ~35 produse identificate ca in afara domeniului (unelte/infrastructura: SSH,
|
||||
server, telefonie, criptare, declaratii D1xx/D3xx/D406 etc.) fara nicio potrivire pe termenii
|
||||
cautati.
|
||||
- Nicio conexiune la baza de date folosita; cifrele despre distributia datelor (ex. randul
|
||||
`id_valuta=0` din `NOM_VALUTE`) sunt preluate din `rec_s4_aplicare.md`, deja documentate.
|
||||
|
||||
## Concluzie
|
||||
|
||||
Doua locuri cu **risc real** confirmat, ambele in codul COMUN partajat (deci efect cross-project):
|
||||
disparitia referintei la aviz de pe facturile `tip=4` retiparite, si textul "Curs: 1.0000 RON/"
|
||||
afisat gresit pe nota facturii electronice/PDF pentru facturile in lei. Restul e risc posibil,
|
||||
dependent de layout-uri `.frx`/`.scx` neconvertite (gap de acoperire cunoscut, nu absenta de risc).
|
||||
Nu s-a gasit niciun consumator cu risc real de **calcul** (sume/discounturi) — toate caile de
|
||||
calcul verificate sunt deja protejate corect de `in_valuta`.
|
||||
|
||||
---
|
||||
|
||||
## Corectie aplicata — riscul REAL #2 (nota "Curs:" din `xmlefactura.prg`)
|
||||
|
||||
Modificare de cod, ceruta explicit de team-lead dupa livrarea inventarului de mai sus. Domeniu:
|
||||
**doar** `D:\ROA\ROAFACTURARE\COMUN\programe\xmlefactura.prg`. Nicio alta copie din suita nu a
|
||||
fost atinsa.
|
||||
|
||||
### Ce s-a schimbat
|
||||
|
||||
Linia 374 (acum singura diferenta fata de fisierul dinainte de editare):
|
||||
```diff
|
||||
- IF !EMPTY(NVL(loDate.curs,0)) AND ATC('curs', m.lcTextAditional) = 0
|
||||
+ IF loDate.in_valuta = 1 AND !EMPTY(NVL(loDate.curs,0)) AND ATC('curs', m.lcTextAditional) = 0
|
||||
lcTextAditional = m.lcTextAditional + Iif(!Empty(m.lcTextAditional), ' # ', '') + "Curs: " + ...
|
||||
ENDIF
|
||||
```
|
||||
Garda adaugata (`loDate.in_valuta = 1 AND`) e preluata **identic** din modelul deja corect din
|
||||
acelasi fisier, la 9 linii mai jos (acum `:385`, era `:384`): `If loDate.in_valuta = 1` /
|
||||
`oinvoice.lastchild.Text = m.mmoneda`, folosit pentru `DocumentCurrencyCode`. Nicio forma noua
|
||||
inventata. Fara comentarii adaugate (regula 2, rezolvari de erori). Diff complet:
|
||||
`D:\ROA\ROAFACTURARE\docs\diff_xmlefactura_garda_valuta.patch`.
|
||||
|
||||
### Verificare pe cazuri (dupa modificare)
|
||||
|
||||
1. **Factura in lei (`in_valuta=0`), `curs=1`** (comportamentul nou, generalizat, al facturilor in
|
||||
lei dupa corectia `PACK_FACTURARE`): inainte, `!EMPTY(NVL(1,0))=.T.` -> nota aparea cu
|
||||
`"Curs: 1.0000 RON/"` (valuta goala). Acum, `loDate.in_valuta = 1` e `.F.` -> intreg `AND`-ul e
|
||||
fals -> nota NU se mai adauga. **Singurul caz care isi schimba comportamentul** (cel vizat).
|
||||
2. **Factura in valuta reala (`in_valuta=1`)**, curs populat normal: `loDate.in_valuta = 1` e
|
||||
`.T.`, restul conditiei neschimbat -> nota apare identic ca inainte. Neschimbat.
|
||||
3. **Factura veche cu `curs` NULL** (orice `in_valuta`): `NVL(NULL,0)=0` -> `!EMPTY(0)=.F.` ->
|
||||
conditia era deja falsa inainte de garda si ramane falsa (garda adaugata doar restrange in plus
|
||||
cazul `in_valuta=0`, nu schimba nimic pe ramura `curs` NULL). Neschimbat.
|
||||
|
||||
Confirmat: doar cazul 1 (facturi in lei cu `curs` efectiv nenul) isi schimba comportamentul, exact
|
||||
riscul identificat.
|
||||
|
||||
### Verificare encoding (byte-level)
|
||||
|
||||
Fisierul contine octeti cp1252 `>=0x80` (`0xEE` = "î", la liniile 1203 si 1330 — "puteti încarca
|
||||
prin SPV"), deci risc de corupere la scriere cu tool care nu pastreaza octetii nativ. Editare
|
||||
facuta cu `perl` in mod raw (`s/.../.../ `), nu cu Edit/Write:
|
||||
- Backup pre-editare: `xmlefactura.prg.pre_runda.bak` (md5 `e800c71bd08e6c472b6fe912437f37f8`,
|
||||
62093 octeti).
|
||||
- Dupa editare: md5 `c9c9f4774346b2e62bfe9c12ea02dfb3`, 62118 octeti (+25 = exact lungimea
|
||||
textului `loDate.in_valuta = 1 AND ` inserat).
|
||||
- Comparatie linie-cu-linie (raw bytes) intre backup si fisierul editat: **1364 linii in ambele,
|
||||
o singura linie diferita (374)** — restul fisierului byte-identic.
|
||||
- Octetii `0xEE` de la liniile 1203/1330 confirmati neschimbati dupa editare.
|
||||
- Scanare pentru markeri de corupere (`EF BF BD` = U+FFFD reincodat): zero potriviri.
|
||||
|
||||
Encoding intact, nicio corupere.
|
||||
|
||||
### Copii identice/asemanatoare in suita — corectie fata de raportul initial
|
||||
|
||||
Raportul initial (sectiunea RISC REAL #2) afirma ca fisierul e "identic prin hash" in ROAEFACTURA,
|
||||
ROASITFIN, ROACONIMPORT, ROAPRINT, ROAPRODUCTIE si ROACONT/OUTPUT — verificare hash directa acum
|
||||
(md5 pe tot arborele `D:\ROA`, exclus `DATABASE`) arata ca afirmatia era **partial gresita**: doar
|
||||
`ROACONIMPORT` si `ROAPRINT` sunt byte-identice intre ele; restul au fiecare continut propriu,
|
||||
divergent de `ROAFACTURARE`. Ce e adevarat si ramane valabil: **toate contin acelasi tipar de cod
|
||||
vulnerabil** (linia cu conditia fara garda pe `in_valuta`), verificat cu grep, o singura aparitie
|
||||
in fiecare fisier.
|
||||
|
||||
**Grup A — fisier byte-identic cu `ROAFACTURARE/COMUN` INAINTE de editarea de azi**
|
||||
(md5 `e800c71bd08e6c472b6fe912437f37f8`, deci acelasi patch de o linie de la `:374` se aplica
|
||||
identic, byte cu byte, in toate):
|
||||
`ROAACNPRO`, `ROAAUTO`, `ROACONT`, `ROACONTRACTE`, `ROADEF`, `ROAGEST`, `ROAIMOB`,
|
||||
`ROAREGISTRATURA`, `ROARES`, `ROASTART` — cale `D:\ROA\<PRODUS>\COMUN\programe\xmlefactura.prg`.
|
||||
(In plus, acelasi hash apare si in foldere de backup istoric fara relevanta:
|
||||
`_backup_comun_conflicts\*`, `_backup_roaimob_comun_conflict\*` — nu sunt copii vii.)
|
||||
|
||||
**Grup B — fisier divergent (alt continut/alte linii in rest), dar cu ACELASI tipar vulnerabil**
|
||||
(conditie identica textual, gasita o singura data per fisier, doar la alt numar de linie):
|
||||
| Produs | Cale | md5 | Linia conditiei |
|
||||
|---|---|---|---|
|
||||
| OUTPUT/ROACONT | `D:\ROA\OUTPUT\ROACONT\COMUN\programe\xmlefactura.prg` | `504dc24e771f6d66e4f028d1347671a8` | 350 |
|
||||
| ROACONIMPORT | `D:\ROA\ROACONIMPORT\COMUN\programe\xmlefactura.prg` | `fa1e389839109ae46da1ef815e102259` | 356 |
|
||||
| ROAEFACTURA | `D:\ROA\ROAEFACTURA\COMUN\programe\xmlefactura.prg` | `200442ad86e180c2484c96367ac9514a` | 356 |
|
||||
| ROAPRINT | `D:\ROA\ROAPRINT\COMUN\programe\xmlefactura.prg` | `fa1e389839109ae46da1ef815e102259` | 356 |
|
||||
| ROAPRODUCTIE | `D:\ROA\ROAPRODUCTIE\COMUN\programe\xmlefactura.prg` | `b71c1d9284d8ee78d02429b04c968a35` | 326 |
|
||||
| ROASITFIN | `D:\ROA\ROASITFIN\COMUN\programe\xmlefactura.prg` | `47bb2e49770713b396e855e8af0ae2ea` | 356 |
|
||||
|
||||
**Grup C — NU are acest bloc de cod deloc** (verificat, nu doar negasit — nu construiesc nota de
|
||||
curs valutar in e-factura): `ROADECL`, `ROAMANAGER`, `ROAPRETURI`, `ROASAL`. Fara risc, fara
|
||||
propagare necesara.
|
||||
|
||||
**Fisierul modificat azi**: doar `D:\ROA\ROAFACTURARE\COMUN\programe\xmlefactura.prg` (md5 nou
|
||||
`c9c9f4774346b2e62bfe9c12ea02dfb3`). Toate celelalte 16 cai listate mai sus (Grup A + Grup B)
|
||||
raman NEATINSE, cu bug-ul inca prezent — propagarea e decizie de proces a lui Marius, nu s-a facut
|
||||
aici.
|
||||
|
||||
### Livrabile
|
||||
|
||||
- Modificare: `D:\ROA\ROAFACTURARE\COMUN\programe\xmlefactura.prg` (linia 374, +garda `in_valuta`).
|
||||
- Patch de review: `D:\ROA\ROAFACTURARE\docs\diff_xmlefactura_garda_valuta.patch`.
|
||||
- Backup pre-editare (ramas pe disc, netracked): `xmlefactura.prg.pre_runda.bak` in acelasi folder.
|
||||
- Aceasta sectiune.
|
||||
|
||||
Fara commit git/svn — asteapta aprobarea patch-ului.
|
||||
358
docs/cercetare/rec_integrari.md
Normal file
358
docs/cercetare/rec_integrari.md
Normal file
@@ -0,0 +1,358 @@
|
||||
# Cercetare: integrare CONTRACTE, politici de preturi, nomenclator ca lista de preturi
|
||||
|
||||
Metoda: `vfp_symbols.ps1` (cache text ROAFACTURARE deja la zi) + Grep pe `.prg`/`.vc2`/`.mn2`.
|
||||
Fapte cu `fisier:linie`; ipoteze marcate `IPOTEZA:`.
|
||||
|
||||
## SUBIECT A - Integrare pagina CONTRACTE (todo #10)
|
||||
|
||||
### 1. Unde exista azi contractele
|
||||
|
||||
Produs separat, working copy completa: `D:\ROA\ROACONTRACTE` (`.git` + `.svn`, `roaContracte.pjx`,
|
||||
`roacontracte.exe`). Structura: `Clase\` (`ofundal.vcx`, `onom_clienti.vcx`, `oOptiuni.vcx`,
|
||||
`roaclienti.vcx`, `ferestre_contracte.vcx` - probabil formularele CRUD de contracte),
|
||||
`Ferestre\`, `Programe\`, `Rapoarte\`, `Meniuri\`, `COMUN\` (propria copie a librariei partajate),
|
||||
`Teste\`, `docs\`.
|
||||
|
||||
**Important**: ROAFACTURARE NU e izolat de contracte azi - are deja o integrare de facturare
|
||||
partiala "pe baza de contract" (vezi punctul 4), care citeste direct din schema Oracle a
|
||||
ROACONTRACTE prin view-uri (`vcontracte`, `fact_vcontracte`, `tipuri_contracte`), fara pagina de
|
||||
editare. `ferestre_contracte.vcx` din ROACONTRACTE contine probabil formularele CRUD care ar
|
||||
trebui aduse in ROAFACTURARE (nu au fost deschise/citite - binar, necesita conversie separata daca
|
||||
se trece la implementare).
|
||||
|
||||
Exista deja urme ale unei integrari partiale de UI in ROAFACTURARE:
|
||||
- `Meniuri\contracte.mnx`/`.mn2` (`D:\ROA\ROAFACTURARE\Meniuri\contracte.mn2:1`) - NU e un meniu de
|
||||
administrare contracte, ci un shortcut-popup cu 3 optiuni de facturare ("Factura fiscala lei /
|
||||
Invoice / Factura fiscala valuta") - cf. continut citit integral.
|
||||
- `Grafice\icon_contracte1.png`, `icon_contracte2.png`, `Grafice\Originale\contracte.png` -
|
||||
iconite deja pregatite in ROAFACTURARE.
|
||||
|
||||
### 2. Cum e integrata azi COMENZI in ROAFACTURARE (sablonul de urmat)
|
||||
|
||||
COMENZI **nu** e produs separat legat prin exe, ci cod montat direct in ROAFACTURARE din
|
||||
`COMUN\` (librarie partajata `gitea.romfast.ro:romfast/comun.git`, cf. CLAUDE.md). Exista si un
|
||||
produs stand-alone `D:\ROA\ROACOMENZI` (cu `.pjx` propriu), dar in ROAFACTURARE comenzile sunt
|
||||
o **pagina/panou montat direct in formularul principal (fundal)**, nu un exe separat lansat.
|
||||
|
||||
Reteta pas cu pas (comenzi ca model pentru contracte):
|
||||
|
||||
1. **Clasa container** `ct_comenzi` din `COMUN\clase\ocomenzi.vcx` (`.vc2` cache:
|
||||
`COMUN\clase\ocomenzi.vc2`) - contine formulare/containere CRUD comenzi
|
||||
(`frm_optiuni_comenzi`, cursoare `vcomenzi_elemente` etc.).
|
||||
2. **Montare in formularul principal**: containerul e plasat ca obiect copil in
|
||||
`Clase\ofundal_facturare.vc2` (form fundal), cu comentariul `< END OBJECT:
|
||||
ClassLib="..\comun\clase\ocomenzi.vcx" BaseClass="container" />` in jurul liniei
|
||||
`Clase\ofundal_facturare.vc2:831`; obiectul se numeste `lb_comenzi`
|
||||
(`Clase\ofundal_facturare.vc2:824`).
|
||||
3. **Butoane de actiune** ("Cw" = clase de tip buton-cu-drept, vezi punctul 3) legate la proceduri
|
||||
business, ex. `Page2.Cw3.do_actiune` -> `DO facturare_comenzi IN oproceduri_facturare.prg`
|
||||
(`Clase\ofundal_facturare.vc2:899-902`).
|
||||
4. **Inregistrare in `Programe\roafacturare.prg`** (entry point):
|
||||
- `SET CLASSLIB TO ocomenzi ADDITIVE` sub comentariul `*** COMENZI`
|
||||
(`Programe\roafacturare.prg:180-181`);
|
||||
- `SET PROCEDURE TO orap_comenzi.prg / onom_comenzi.prg / update_comenzi.prg ADDITIVE`
|
||||
(`Programe\roafacturare.prg:239-242`), tot sub `*** COMENZI`;
|
||||
- variabile module: `PRIVATE pocomenzi,pocomenzielemente,polucrari,pocomenzi2,polucrarielemente`
|
||||
(`Programe\roafacturare.prg:246-247`).
|
||||
- Toate cele 3 `.prg` (`orap_comenzi.prg`, `onom_comenzi.prg`, `update_comenzi.prg`) si clasa
|
||||
`ocomenzi.vcx`/`.vct` locuiesc fizic in `COMUN\programe\` / `COMUN\clase\`, dar sunt
|
||||
inregistrate ca membri ai proiectului `roafacturare.pjx` (confirmat prin Grep pe `.pjx`:
|
||||
`COMUN\clase\ocomenzi.vcx`, `COMUN\programe\orap_comenzi.prg` etc. apar in el).
|
||||
5. **Business logic de facturare din comenzi**: `Procedure facturare_comenzi` in
|
||||
`COMUN\programe\oproceduri_facturare.prg:139-141` - un simplu `factureaza(3)` (tip document 3
|
||||
= "din comanda", motorul central `factureaza()` face restul).
|
||||
6. **Meniu**: nu exista `Meniuri\comenzi.mnx` separat in ROAFACTURARE - comenzile nu au intrare de
|
||||
meniu proprie, ci doar butonul `Cw3` de pe pagina fundal (Page2 = "Facturare"). Contractele au
|
||||
deja `Meniuri\contracte.mnx` dar cu alt continut (shortcut factura), deci pentru pagina noua de
|
||||
contracte ar trebui fie extins acest fisier, fie creat altul.
|
||||
|
||||
Concluzie sablon: pentru CONTRACTE ar insemna (a) o clasa container tip `ct_contracte` (posibil
|
||||
adaptata din `ferestre_contracte.vcx` al ROACONTRACTE, mutata/duplicata in `COMUN\clase\`), (b)
|
||||
montarea ei ca obiect in `ofundal_facturare.vc2` langa `lb_comenzi`, (c) inregistrare `SET
|
||||
CLASSLIB`/`SET PROCEDURE` in `roafacturare.prg` sub un bloc nou `*** CONTRACTE`, (d) adaugare in
|
||||
`roafacturare.pjx`.
|
||||
|
||||
### 3. Mecanismul de DREPTURI pe obiecte
|
||||
|
||||
Sursa: `COMUN\programe\acces_meniu.prg` (fisier citit integral).
|
||||
|
||||
- **Sursa de date**: view Oracle `contafin_oracle.vdef_util_obiecte`, interogat cu
|
||||
`select cheie,id_firma from contafin_oracle.vdef_util_obiecte where id_util=?gnIdUtil and
|
||||
id_program=?gnIdProgram and id_firma=?gnIdFirma` (`acces_meniu.prg:29-31`), rezultat in cursorul
|
||||
`crsdrepturi` (o singura coloana cheie relevanta: `cheie`, string).
|
||||
- **Codificarea cheii**: concatenare de "caractere de nivel" - `Chr(lnKey)` pentru fiecare nivel de
|
||||
pageframe/pagina (`dezactiveaza_obiecte_pageframe`, `acces_meniu.prg:103-165`, recursiv pe
|
||||
subpageframe-uri), plus un cod de 2 cifre pentru fiecare buton `Cw*`:
|
||||
`lcCheie = lcKey + Padl(Alltrim(Str(.Objects(l).nid_cw)), 2, '0')` (`acces_meniu.prg:138`).
|
||||
Fiecare obiect `Cw*` are proprietatea `nid_cw` (numarul lui in cadrul paginii) si la runtime i se
|
||||
seteaza `ccheie` (`acces_meniu.prg:140`) si `coptiuni_active` (lista de operatii CRUD permise,
|
||||
citita din caracterele urmatoare cheii - `acces_meniu.prg:141-149`). Butonul apeleaza
|
||||
`.Objects(l).activeaza()` / `.dezactiveaza()` in functie de gasire (`acces_meniu.prg:150-152`).
|
||||
- **Pentru imagini/iconite** (nivel diferit, folosit pe alte forme): proprietate `ccod` pe obiect
|
||||
(`acces_meniu.prg:48`), aceeasi logica de cautare in `crsdrepturi`.
|
||||
- **Cod de meniu (pad-uri)**: `GetAccesByCod(tcCod, tcAccesDefault)` (`acces_meniu.prg:236-276`)
|
||||
cauta o cheie explicita (cod optiune meniu, ex. "ZA01") in `crsdrepturi` si intoarce lista de
|
||||
operatii permise (ex. "1;2;3;4").
|
||||
- **Punct de intrare**: `verifica_drepturi(tcObiectFundal, tcPageFrame)`
|
||||
(`acces_meniu.prg:9-15`) apelat din formularul fundal (`Ferestre\fundal.sc2:699`:
|
||||
`verifica_drepturi('gofundal','_pgfrmbase1')`), care incarca `crsdrepturi` o singura data per
|
||||
firma (cache in memorie, `citeste_drepturi`, `acces_meniu.prg:17-37`) si dezactiveaza in cascada
|
||||
paginile/butoanele/meniurile fara drept.
|
||||
- **Administrare drepturi** (unde se declara catalogul de obiecte si se atribuie pe grupuri):
|
||||
`COMUN\clase\drept_grupuri.vc2` - `frm_grupuri`, apel catre pachetul Oracle
|
||||
`PACK_DREPTURI.grupdreptmodproc` (`COMUN\clase\drept_grupuri.vc2:39`) si `citeste_drepturi
|
||||
(loRec.id_grup)` (`COMUN\clase\drept_grupuri.vc2:205`).
|
||||
|
||||
IPOTEZA: catalogul efectiv de "obiecte disponibile pentru ROAFACTURARE" (denumirile/codurile
|
||||
`nid_cw`/`ccod`/coduri de meniu, ex. cele pentru COMENZI) e definit **partial in designerul VFP**
|
||||
(proprietatea `nid_cw` seteaza pe fiecare buton la design-time in `.scx`/`.vcx`) si **partial
|
||||
server-side** in schema Oracle `contafin_oracle` (tabelul din spatele view-ului
|
||||
`vdef_util_obiecte`, populat probabil printr-un script de instalare/migrare, nu vazut in sursa
|
||||
VFP). Pentru "comasarea" drepturilor ROACONTRACTE + ROAFACTURARE mentionata in cerere, ar trebui
|
||||
inspectat acest tabel server-side (in afara sursei VFP disponibile aici) plus alocarea de noi
|
||||
`nid_cw` pentru butoanele noi de contracte, fara sa coincida cu cele deja folosite de COMENZI/
|
||||
lista de preturi/avize pe aceeasi pagina.
|
||||
|
||||
Exemplu concret COMENZI: butonul `Page2.Cw3` (facturare din comenzi) foloseste automat cheia
|
||||
`<cheie_pagina>+'03'` (Cw3 => `nid_cw=3`); pentru un buton nou de contracte pe aceeasi pagina ar
|
||||
trebui un `nid_cw` neutilizat (ex. 11+, dat fiind ca Page2 are deja Cw1..Cw9 conform
|
||||
`Clase\ofundal_facturare.vc2:882-926`).
|
||||
|
||||
### 4. Facturarea pe baza de comanda / pe baza de contract
|
||||
|
||||
**Comanda -> factura**: `Procedure facturare_comenzi` (`COMUN\programe\oproceduri_facturare.prg:
|
||||
139-141`) => `factureaza(3)`. Cautarea comenzii disponibile pentru facturare:
|
||||
`Function caut_comanda_gestiune` (`COMUN\programe\oproceduri_facturare.prg:1961-1983`), citeste
|
||||
din view-ul `vcomenzi` (`... FROM ] + gcS + [.vcomenzi`), filtru
|
||||
`facturat = 0 and interna = 3 ... ` (linia 1977).
|
||||
|
||||
**"Pe baza de contract" EXISTA DEJA**, mai complet decat comenzile pe alocuri:
|
||||
- `Procedure facturare_contracte(tcTip)` (`COMUN\programe\oproceduri_facturare.prg:119-136`) -
|
||||
primeste tipul de document ("FACTURA LEI"/"INVOICE"/"FACTURA VALUTA") si apeleaza
|
||||
`factureaza(2)`/`factureaza(6)`/`factureaza(52)`.
|
||||
- Buton pe pagina fundal: `Page2.Cw2.do_actiune` (`Clase\ofundal_facturare.vc2:886-897`) - meniu
|
||||
`xmenu` cu cele 3 optiuni, cheama `facturare_contracte`.
|
||||
- **Cautare contract**: `Function caut_contract_facturare(tnIdPart, tcSirTipFacturare)`
|
||||
(`COMUN\programe\oproceduri_facturare.prg:1986-2021`) - citeste din view-ul `fact_vcontracte`
|
||||
(`select id_ctr, contract, numar, data, denumire, scadenta_incasare, opt_facturare,
|
||||
text_standard, afisare_scadenta FROM fact_vcontracte`, linia 2001), filtrat pe
|
||||
`opt_facturare in (...)` si `id_part`.
|
||||
- **Alegerea contractului la factura**: `frm_date_factura.do_cauta_contract`
|
||||
(`COMUN\clase\ofacturare.vc2:9067-9115`) si `frm_date_aviz.do_cauta_contract`
|
||||
(`COMUN\clase\ofacturare.vc2:7049-7051`) apeleaza `caut_contract_facturare`.
|
||||
- **Editorul de articole pe factura** are un tab/grid dedicat contractelor:
|
||||
`frm_facturare_articole` cu controale `grd_contracte`, `cb_contracte` (combobox cu ratele /
|
||||
contractele), populate din cursorul `crscontracte` (`COMUN\clase\ofacturare.vc2:15069-15107` si
|
||||
in jur). Optiunea `opt_facturare` din `fact_vcontracte`/`crsfactura` marcheaza randurile "din
|
||||
contract" (`COMUN\programe\oproceduri_facturare.prg:176-177`, `Inlist(opt_facturare,1,2)` in alt
|
||||
context legat de seturi).
|
||||
- **Aviz pe baza de contract**: exista si un tip de aviz "26 - catre clienti din contract"
|
||||
(`COMUN\programe\oproceduri_facturare.prg:207`, enumerat si in `caut_avize`,
|
||||
`COMUN\programe\oproceduri_facturare.prg:2045`), apelat din `emitere_aviz_clienti(tnTip=3)`.
|
||||
|
||||
Concluzie: **motorul de facturare din contract e deja complet functional** in ROAFACTURARE (citire
|
||||
din schema ROACONTRACTE prin view-uri Oracle `vcontracte`/`fact_vcontracte`/`tipuri_contracte`).
|
||||
Ce lipseste conform cererii e (a) o **pagina de editare CRUD a contractelor** in ROAFACTURARE
|
||||
(azi doar in exe-ul separat ROACONTRACTE) si (b) **rapoarte de contracte** in ROAFACTURARE, plus
|
||||
(c) unificarea drepturilor. Nu a fost gasit niciun raport de contracte in
|
||||
`ROAFACTURARE\Rapoarte\` (glob `*contract*` nu a dat `.frx` in Rapoarte, doar meniu/iconite).
|
||||
|
||||
---
|
||||
|
||||
## SUBIECT B - Politici de preturi (todo #11)
|
||||
|
||||
### 5. Unde sunt azi definite/editate
|
||||
|
||||
Produs separat, mic, dedicat: `D:\ROA\ROAPRETURI` (`.pjx` propriu, `roapreturi.exe`). Structura:
|
||||
`Programe\onom_preturi.prg`, `Programe\update_preturi.prg`, `Programe\update_nomenclator.prg`,
|
||||
`Clase\opreturi.vcx`, `Clase\onom_preturi.vcx`, `Clase\ofundal_preturi.vcx`,
|
||||
`Clase\ofundal_roapreturi.vcx`, `Ferestre\fundal.scx`. (Continutul acestor clase nu a fost convertit
|
||||
in text - ROAPRETURI nu are un cache text propriu generat in aceasta sesiune; doar structura de
|
||||
fisiere a fost inspectata.)
|
||||
|
||||
Interfata de editare pare sa fie un produs desktop de sine statator, distinct de ROAFACTURARE si de
|
||||
ROACONT, focalizat strict pe politici/liste de preturi si pe actualizarea nomenclatorului
|
||||
(`update_nomenclator.prg` sugereaza ca ROAPRETURI scrie si in nomenclatorul comun de articole).
|
||||
|
||||
### 6. Tabele/view-uri implicate (identificate din ROAFACTURARE)
|
||||
|
||||
Din codul ROAFACTURARE care CITESTE politici de preturi (nu editeaza), gasite:
|
||||
- `vcrm_politici_preturi` - view folosit in cautare dupa drepturi utilizator
|
||||
(`COMUN\clase\baza.vc2:10087`, `:10157`, `:10502-10512`). Interogare efectiva:
|
||||
`select nume_lista_preturi, id_pol from crm_vpolpretcurutil` (`COMUN\clase\baza.vc2:10504`) -
|
||||
deci exista si view-ul `crm_vpolpretcurutil` ("politica de pret curenta pentru utilizator"),
|
||||
cheie `id_pol`.
|
||||
- `vvanzari_detalii` - contine coloana `nume_lista_preturi` folosita in rapoarte de marfa
|
||||
(`COMUN\clase\configurare.vc2:3915-3972`, `frm_raport_marfa`).
|
||||
- Meniu dedicat facturarii pe lista de preturi: `Meniuri\politica.mnx`/`.mn2`/`.MPR` in
|
||||
ROAFACTURARE; procedura `facturare_lista_de_preturi` = `Do politica.mpr`
|
||||
(`COMUN\programe\oproceduri_facturare.prg:113-116`), buton `Page2.Cw1.do_actiune`
|
||||
(`Clase\ofundal_facturare.vc2:882-884`).
|
||||
- Prefixul `crm_`/`CRM` in numele tabelelor/view-urilor (`vcrm_politici_preturi`,
|
||||
`crm_vpolpretcurutil`) sugereaza schema/modul Oracle numit "CRM", separat de schema principala
|
||||
de facturare (`gcS`). IPOTEZA: politicile de pret sunt un modul Oracle transversal (folosit si
|
||||
de ROAGEST, ROAPRETURI, ROACONTRACTE), nu proprietatea exclusiva a unui singur produs VFP.
|
||||
- Comenzile (ROACOMENZI/`ocomenzi.vcx`) au propriul mecanism de asociere pret-din-comanda:
|
||||
globale `gnIdPoliticaPret`, `gnId_lista_preturi_PV` (`Programe\roafacturare.prg:467,469`),
|
||||
folosite si in `frm_optiuni_comenzi` (`COMUN\clase\ocomenzi.vc2:6488-6686`, variabila
|
||||
`gnID_LISTA_PRETURI_PV` = politica de pret "de productie" folosita la generarea automata a
|
||||
comenzilor). Cursorul de articole al comenzii are coloanele `id_pol`, `nume_lista_preturi`,
|
||||
`pret`, `pret_cu_tva`, `ptva` direct in el (`COMUN\clase\ocomenzi.vc2:1227-1229`, cursor creat
|
||||
din view-ul `vcomenzi_elemente`).
|
||||
|
||||
Nu a fost gasita nicio schema DBF/DDL explicita pentru "politici de preturi" / "liste de preturi"
|
||||
in sursa VFP (tabelele reale sunt Oracle, definite server-side; VFP le vede doar prin view-uri
|
||||
enumerate mai sus). N-a fost identificat un tabel separat de "note contabile asociate politicii de
|
||||
pret" in codul cercetat - contul contabil de vanzare pare sa vina din nomenclatorul de articole
|
||||
(`nom_articole.cont`, vezi punctul 10), nu dintr-o tabela separata legata de politica.
|
||||
|
||||
### 7. Ce foloseste ROAFACTURARE azi din aceste date
|
||||
|
||||
- **Facturare pe lista de preturi** (`Do politica.mpr`) - flux complet de vanzare pe baza unei
|
||||
politici de pret selectate (analog cu vanzarea din stoc/comenzi/contract), tip document
|
||||
distinct in motorul central `factureaza()`.
|
||||
- **Cautare/afisare politica dupa drepturi utilizator** (`COMUN\clase\baza.vc2:10502-10512`) -
|
||||
ROAFACTURARE citeste `crm_vpolpretcurutil` pentru a limita politicile vizibile la cele pe care
|
||||
utilizatorul are drept (alt strat de drepturi, distinct de `acces_meniu.prg` - specific pe
|
||||
politici de pret, posibil gestionat tot server-side prin pachetul `PACK_DREPTURI`).
|
||||
- **Rapoarte de vanzari pe lista de preturi** (`frm_raport_marfa`,
|
||||
`COMUN\clase\configurare.vc2:3915-3972`) - grupare/însumare pe `nume_lista_preturi`.
|
||||
- Nu editeaza politici/liste - doar le CITESTE si le foloseste ca sursa de pret la facturare/
|
||||
raportare. Editarea (adaugare politica, adaugare articole in politica, preturi) ramane in
|
||||
ROAPRETURI.
|
||||
|
||||
Concluzie pentru migrare: ce ar trebui **mutat efectiv in ROAFACTURARE** (conform cererii - "se
|
||||
folosesc numai in programul ROAFACTURARE") e interfata de editare (`opreturi.vcx`/
|
||||
`onom_preturi.vcx` din ROAPRETURI), nu structura de date (Oracle, deja partajata/citita corect).
|
||||
Rapoartele si drepturile pe liste de preturi trebuie de asemenea aduse ca pagina/panou in
|
||||
ROAFACTURARE, dupa acelasi sablon COMENZI descris la punctul 2.
|
||||
|
||||
---
|
||||
|
||||
## SUBIECT C - Nomenclatorul de articole ca lista de preturi virtuala (todo #12)
|
||||
|
||||
### 8. Structura tabelei de nomenclator
|
||||
|
||||
Tabela Oracle **`catalog_articole`**, expusa prin view-ul **`vnom_articole`** (si `vnom_articole2`
|
||||
pentru un al doilea tip - vezi `nom_articole2_nou`, `COMUN\programe\onomenclatoare.prg:1376-1396`,
|
||||
tabela `catalog_articole2`).
|
||||
|
||||
Coloane identificate din interogari/scatter (nu e o lista exhaustiva - vin din SELECT-uri
|
||||
punctuale, nu din DDL):
|
||||
`id_articol, denumire, codmat, codmatf (cod furnizor), codbare, um, grupa, subgrupa, id_grupa,
|
||||
id_subgrupa, dnf, cont (cont contabil, 3-4 caractere), acont, inactiv, sters, in_stoc, in_crm,
|
||||
tip (ex. 1 = manopera pt. ROAACNPRO), id_part/partener (pt. articole legate de furnizor/client)`.
|
||||
Surse: `COMUN\clase\ocriterii.vc2:1531` (`select denumire, codmat, um, grupa, subgrupa, id_grupa,
|
||||
id_subgrupa, dnf, cont, acont, inactiv, id_articol from vnom_articole`),
|
||||
`COMUN\programe\onomenclatoare.prg:1345-1353` (`in_crm`, `in_stoc`, `tip`),
|
||||
`COMUN\clase\ointroduceri.vc2:9631` (`in_stoc, cont`).
|
||||
|
||||
**Nicio coloana de pret** nu a fost gasita direct pe `nom_articole`/`catalog_articole` (grep
|
||||
`pret_v|pretv|pret_lista` in `onomenclatoare.prg` = fara rezultate; scatter-ul din
|
||||
`nom_articole_nou` nu populeaza niciun camp de pret). Confirma punctul 11 mai jos.
|
||||
|
||||
**Formular de editare**: `frm_catalog_articole` (grid/cautare) si `frm_catalog_articole_nou`
|
||||
(fisa), ambele in `COMUN\clase\onom_articole.vc2` (`:531-599`, `:1655-1733`), salvare prin
|
||||
`cus_odata_catalog_articole.salvare` si `Adauga_Modifica_Inregistrare('catalog_articole', ...)`
|
||||
(`COMUN\programe\onomenclatoare.prg:1367,1443`). Deschidere din meniu:
|
||||
`Procedure viz_catalog_articole` (`COMUN\programe\oproceduri_articole.prg:62-122`).
|
||||
|
||||
**Important pentru subiectul B/C**: `nom_articole_nou` (`COMUN\programe\onomenclatoare.prg:
|
||||
1343-1353`) marcheaza acelasi articol cu `in_crm = 1` cand programul curent e ROAPRETURI sau
|
||||
ROACONTRACTE, respectiv `in_stoc = 1` in rest (inclusiv ROAFACTURARE) - **nomenclatorul de
|
||||
articole e deja UNIC/PARTAJAT** intre ROAFACTURARE, ROAPRETURI, ROACONTRACTE si ROAACNPRO (aceeasi
|
||||
tabela `catalog_articole`), flagurile `in_stoc`/`in_crm`/`tip` fiind doar clasificari de
|
||||
utilizare, nu tabele separate. Asta simplifica mult todo #12: nomenclatorul nu trebuie replicat,
|
||||
doar completat cu campuri de pret/tva/cont-vanzare si folosit direct ca sursa de pret la
|
||||
facturare.
|
||||
|
||||
### 9. Mecanismul actual de "lista de articole din stoc ca lista de preturi virtuala"
|
||||
|
||||
Confirmat: e mecanismul de **"vanzare din stoc/gestiune"**, un tip de facturare paralel cu
|
||||
"lista de preturi"/"contract"/"comanda", identificat prin variabila globala `gnTipGest`:
|
||||
- `Procedure vanzare_materii_prime` -> `gnTipGest = 2`, `Do vanzare1.mpr`
|
||||
- `Procedure vanzare_produse` -> `gnTipGest = 4`, `Do vanzare2.mpr`
|
||||
- `Procedure vanzare_marfa_pret_achi` -> `gnTipGest = 5`, `Do vanzare3.mpr` (marfa la pret de
|
||||
achizitie)
|
||||
- `Procedure vanzare_marfa_pret_vanz` -> `gnTipGest = 6`, `Do vanzare4.mpr` (marfa la pret de
|
||||
**vanzare**)
|
||||
- `Procedure vanzare_marfa_pret_achi_vanz` -> `gnTipGest = 7`, `Do vanzare5.mpr`
|
||||
(toate in `COMUN\programe\oproceduri_facturare.prg:1505-1534`; butoane `Page2.Cw5..Cw9` in
|
||||
`Clase\ofundal_facturare.vc2:908-926`).
|
||||
|
||||
Gestiunile disponibile per tip se filtreaza prin `Procedure selecteaza_gestiuni`
|
||||
(`COMUN\programe\oproceduri_facturare.prg:1536-1565`), pe view-ul `vnom_GESTIUNI` filtrat
|
||||
`nr_pag = ?gnTipGest`, plus un al doilea nivel de drept pe gestiuni (view-urile
|
||||
`vgest_coresp_grupe_gestiuni` / `vgest_coresp_util_grupe`, linia 1552-1555) - deci "lista de
|
||||
preturi virtuala" = stocul unei gestiuni, cu control de acces pe gestiune (nu pe politica de
|
||||
pret).
|
||||
|
||||
Motorul de scriere: `Function oscrie_vanzare_din_stoc` in `COMUN\programe\ofacturare_stoc.prg:
|
||||
104-...`, apelat din `initializeaza_vanzare_din_stoc` (`ofacturare_stoc.prg:31-99`). Comentariu
|
||||
explicit in cod: *"in vanzari_detalii scriu pretul cu tva daca am marfa la pret de vanzare, daca
|
||||
nu scriu pretul de vanzare fara tva"* (`ofacturare_stoc.prg:107`), cu
|
||||
`lnPretCuTva = Iif(INLIST(gnTipGest,6,7), 1, 0)` (linia 111) - deci flagul "pret cu TVA" e
|
||||
determinat de TIPUL de vanzare din stoc ales (6/7 = la pret de vanzare), nu citit dintr-o coloana
|
||||
a nomenclatorului.
|
||||
|
||||
Cursorul-cheie `crsvanztemp` (`ofacturare_stoc.prg:137-139`) are coloanele:
|
||||
`id_articol, Pret, proc_tvav, id_jtva_coloana, cantitate, discount_unitar, id_gestiune, Cont
|
||||
(c4), pret_cu_tva, serie, id_valuta, codmat, Curs, multiplicator, pret_achizitie, pretd,
|
||||
id_valuta_d, id_rul_aux, taxcode, lot`.
|
||||
|
||||
### 10. Lantul de cod: pret, valuta, %TVA, pret_cu_tva, cont vanzare - la facturare "din stoc"
|
||||
|
||||
Din structura `crsvanztemp` (punctul 9) rezulta explicit lantul folosit azi cand se factureaza
|
||||
"virtual" din stoc (echivalentul cerut pentru nomenclator-ca-lista-de-preturi):
|
||||
- **Pret**: coloana `Pret` in `crsvanztemp`, luata din inregistrarea de gestiune/stoc (miscarea de
|
||||
intrare), nu din nomenclator - `pret_achizitie` separat pentru pretul de achizitie.
|
||||
- **Valuta**: `id_valuta`, `Curs`, plus varianta in alta valuta `pretd`/`id_valuta_d` (pret dublu,
|
||||
pentru afisare in a doua valuta).
|
||||
- **%TVA**: `proc_tvav` + `id_jtva_coloana` (coloana de defalcare TVA in jurnal) + `taxcode` (cod
|
||||
fiscal pt. integrari, ex. eFactura).
|
||||
- **Flag pret_cu_tva**: `pret_cu_tva` in cursor, calculat din `gnTipGest` (`ofacturare_stoc.prg:
|
||||
111`), NU citit dintr-o coloana persistenta a articolului.
|
||||
- **Cont vanzare (echivalent 4111=7xx)**: coloana `Cont c(4)` in `crsvanztemp` - cont contabil pe
|
||||
4 caractere (ex. "707x"/"701x"), scris explicit in cursor la nivel de linie de vanzare. Sursa lui
|
||||
cea mai probabila (nu confirmata cu linie exacta de SELECT in aceasta cercetare, cursorul e
|
||||
populat mai jos in fisier, dincolo de zona citita) e coloana `nom_articole.cont` (confirmata ca
|
||||
existenta la punctul 8) sau contul gestiunii (`nom_gestiuni`) - **IPOTEZA**: trebuie verificat
|
||||
punctual restul lui `oscrie_vanzare_din_stoc` (fisierul continua dupa linia 140, necitit
|
||||
integral in aceasta trecere) pentru sursa exacta linie-cu-linie a lui `Cont`.
|
||||
|
||||
Pentru comparatie, la facturarea pe **lista de preturi/politica** (nu pe stoc), pretul/valuta/TVA
|
||||
vin din politica de pret (view `crm_vpolpretcurutil`/`vcrm_politici_preturi`, punctul 6), deci
|
||||
lantul e diferit dupa tipul de facturare ales (`gnTipGest` vs. `id_pol`).
|
||||
|
||||
### 11. Coloane de pret existente/partial folosite in nomenclator
|
||||
|
||||
**Nu exista azi nicio coloana de pret pe `nom_articole`/`catalog_articole`** (cautare explicita
|
||||
fara rezultate). Exista insa deja doua campuri reutilizabile direct pentru scenariul din cerere:
|
||||
- `cont` (cont contabil de vanzare/achizitie, deja pe articol - vezi punctul 8) - poate fi folosit
|
||||
ca "nota contabila" fara tabel separat.
|
||||
- Flagurile `in_stoc` / `in_crm` - clasifica deja fiecare articol dupa modul de utilizare (stoc
|
||||
vs. politica de pret / CRM), un precedent direct pentru un viitor flag suplimentar de tipul
|
||||
"articol cu pret propriu in nomenclator" daca se implementeaza todo #12.
|
||||
|
||||
Nu au fost gasite coloane de tipul `pret`, `pret_vanzare`, `valuta_pret`, `ptva` direct pe
|
||||
nomenclator - toate preturile de vanzare vin azi fie din politici de pret (Oracle, schema CRM),
|
||||
fie din miscarile de gestiune/stoc (nu din articolul insusi). Implementarea todo #12
|
||||
("nomenclatorul direct ca lista de preturi, fara politica + nota contabila asociate") ar necesita
|
||||
adaugarea a cel putin: pret (+valuta), procent TVA, flag pret_cu_tva pe `catalog_articole`/
|
||||
`nom_articole` - camp nou, nu o coloana ascunsa deja existenta.
|
||||
|
||||
---
|
||||
|
||||
## Rezumat surse cheie (fisier:linie)
|
||||
|
||||
- Sablon COMENZI: `Programe\roafacturare.prg:180-181,239-247`; `Clase\ofundal_facturare.vc2:
|
||||
760-926`; `COMUN\clase\ocomenzi.vc2`.
|
||||
- Drepturi: `COMUN\programe\acces_meniu.prg` (tot fisierul, 306 linii).
|
||||
- Facturare contract: `COMUN\programe\oproceduri_facturare.prg:119-136,1986-2021`;
|
||||
`COMUN\clase\ofacturare.vc2:9067-9115,15069-15107`.
|
||||
- Politici de pret: `COMUN\clase\baza.vc2:10087,10157,10453-10512`;
|
||||
`COMUN\programe\oproceduri_facturare.prg:113-116`.
|
||||
- Vanzare din stoc (lista virtuala): `COMUN\programe\oproceduri_facturare.prg:1505-1534`;
|
||||
`COMUN\programe\ofacturare_stoc.prg:31-140`.
|
||||
- Nomenclator articole: `COMUN\programe\onomenclatoare.prg:1302-1373`;
|
||||
`COMUN\clase\onom_articole.vc2:531-599,1655-1733`.
|
||||
243
docs/cercetare/rec_pret_lazy.md
Normal file
243
docs/cercetare/rec_pret_lazy.md
Normal file
@@ -0,0 +1,243 @@
|
||||
# Cercetare: lant pret (#12) + editare politici pret (#11/#10) + lazy loading
|
||||
|
||||
## REZUMAT (max 30 linii, focus A2 + C2)
|
||||
|
||||
**A2 — NU exista niciun fallback la nomenclator azi.** Confirmat din chiar view-ul care alimenteaza
|
||||
majoritatea ramurilor lui `cursor_preturi` (`fact_vpreturi_utilizator`, definit in
|
||||
`D:\ROA\DATABASE\SCRIPTURI\2009\4\ff_2009_04_21_03_FACTURARE.sql:11-50`): clauza
|
||||
`and d.id_pol is not null` (linia 49) e o conditie **obligatorie** pe `crm_politici_pret_art d` —
|
||||
un articol nu apare deloc in lista de vanzare daca nu are un rand in `CRM_POLITICI_PRET_ART` pentru
|
||||
politica activa a utilizatorului. `NOM_ARTICOLE` e joinat doar pentru `um/denumire/codmat/codbare/
|
||||
in_stoc` (descriptive), niciodata pentru `pret/valuta/proc_tvav`. In `PACK_FACTURARE.cursor_preturi`
|
||||
insusi (`ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql:2121-2627`) acelasi tipar se repeta in toate
|
||||
ramurile (2, 45, 1/2, 5/6/10/52, 7, else/aviz): driver-ul e mereu `CRM_POLITICI_PRET_ART`/politica,
|
||||
niciun `NVL`/`COALESCE` catre `catalog_articole`/`nom_articole` pentru pret. Nu exista deloc referinte
|
||||
la `catalog_articole` in tot pachetul `PACK_FACTURARE` (grep pe fisierul de 16948 linii: 0 hit-uri).
|
||||
**Concluzie: fallback-ul de #12 chiar trebuie construit de la zero.** Locul ieftin de inserat: in
|
||||
`fact_vpreturi_utilizator` si/sau direct in `cursor_preturi`, un `UNION ALL`/`LEFT JOIN` suplimentar
|
||||
care aduce articolele din `catalog_articole` **fara** rand in `CRM_POLITICI_PRET_ART` pentru
|
||||
politica curenta, cu pret/valuta/tva **NULL sau valori implicite din optiuni firma** — deoarece
|
||||
`catalog_articole` nu are nicio coloana de pret/valuta/tva (confirmat de echipa, si verificat: n-am
|
||||
gasit `PRET`/`ID_VALUTA`/`PROC_TVAV` pe `NOM_ARTICOLE`/`CATALOG_ARTICOLE` in DDL). Fallback-ul e deci
|
||||
"articolul apare, dar utilizatorul trebuie sa completeze pretul manual" — nu un pret implicit real.
|
||||
|
||||
**C2 — Exista deja un sablon de lazy loading, complet si reutilizabil**, in
|
||||
`COMUN\clase\_ct_base.vc2:278-281` (`do_activeaza_container` → `This.actualizeaza_cursoare()`), legat
|
||||
la `PageX.Activate` (`Clase\ofundal_facturare.vc2:1006-1008` pentru comenzi). Implementarea reala e
|
||||
in `COMUN\clase\ocomenzi.vc2:1088-1104`: cursorul se creeaza o singura data (guard
|
||||
`!Used('crscomenzi') Or gcS!=This.cSchema Or ...schimbare sectie`), cu un `WHERE` imposibil
|
||||
(`id_comanda = -9999999`) — deci structura se creeaza dar nu se aduc date. Datele reale vin abia la
|
||||
`do_cauta()` (`ocomenzi.vc2:1484-1510`), care trimite un `WHERE` filtrat prin `gencursor`/
|
||||
`ca_baza1.afisare()` — deci cautarea e deja server-side (Oracle), nu filtrare locala. **Acesta e
|
||||
sablonul de refolosit pentru #11/#10, exact cum indica deja `plan_10_integrare_contracte.md` S3.**
|
||||
Atentie: baza `_ct_base.actualizeaza_cursoare` (linia 231-232) e un stub gol — clasa container noua
|
||||
(`ct_preturi`/`ct_contracte`) trebuie sa suprascrie explicit `actualizeaza_cursoare`, dupa modelul
|
||||
`ocomenzi`, nu doar sa mosteneasca `_ct_base`. `ct_contracte` din ROACONTRACTE **nu** face asta azi
|
||||
(vezi C4) — deci nu e lazy, desi mosteneste acelasi `_ct_base`.
|
||||
|
||||
---
|
||||
|
||||
## A. Lantul de determinare a pretului
|
||||
|
||||
### A1. `cursor_preturi` — surse pe ramura (spec `:335-343`, body `:2121-2627`,
|
||||
`ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql`)
|
||||
|
||||
Toate ramurile pornesc din `pack_facturare.initializeaza_facturare` + `completare_politica_stoc` +
|
||||
`verifica_cursuri_valute` (:2132-2136), apoi `CASE V_TIP`:
|
||||
|
||||
- **V_TIP=45 (restaurant)**, `:2143-2247`: subselect A = politica activa a utilizatorului
|
||||
(`utilizatori_rol_intern` → `politici_grupuri` → `crm_politici_preturi` → `crm_note_vanzari` →
|
||||
`note_contabile`, filtrat pe `datai/datas` fata de luna curenta si `id_sucursala`), apoi
|
||||
`LEFT JOIN CRM_POLITICI_PRET_ART B ON A.ID_POL=B.ID_POL`, `LEFT JOIN NOM_ARTICOLE C`. **Pret**:
|
||||
`B.PRET`/`B.DISCOUNT_UNITAR` convertite prin curs (`F.CURS`) daca valuta politicii ≠ valuta
|
||||
nationala. **Valuta**: `B.ID_VALUTA` → `NOM_VALUTE G`. **TVA%**: `B.PROC_TVAV` (direct din
|
||||
`CRM_POLITICI_PRET_ART`, nicio referinta la `ID_JTVA_COLOANA` in acest cursor). **Flag
|
||||
pret_cu_tva**: `A.PRETURI_CU_TVA` (de pe `crm_politici_preturi`, nu per-articol). **Cont**:
|
||||
`'371' AS CONT` — **hardcodat**, nu vine din nicio tabela.
|
||||
- **V_TIP IN (1,2) (factura lei)**, `:2248-2372`: acelasi tipar (A/B/C), plus `LEFT JOIN` pe `STOC`
|
||||
pentru cantitate gestionabila (E) si pe `CURS`/`NOM_VALUTE` (F/G). Nicio coloana `CONT` in select.
|
||||
- **V_TIP IN (5,6,10,52) (valuta)** si **V_TIP=7 (credit note)**, `:2374-2524`: sursa e view-ul
|
||||
`FACT_VPRETURI_UTILIZATOR A` (nu mai construieste politica inline), plus `STOC` (C) si `CURS`/
|
||||
`NOM_VALUTE` (D/E). Filtru `A.ID_VALUTA=V_ID_VALUTA AND A.IN_VALUTA=1` (sau `A.ID_POL=
|
||||
pack_facturare.nid_politica_stoc` la tip 5/6/10/52). Nicio coloana `CONT`.
|
||||
- **ELSE (aviz)**, `:2526-2624`: tot din `FACT_VPRETURI_UTILIZATOR A`, fara filtru pe valuta. Nicio
|
||||
coloana `CONT`.
|
||||
|
||||
**Definitia `FACT_VPRETURI_UTILIZATOR`** (cea mai recenta gasita, `D:\ROA\DATABASE\SCRIPTURI\2009\4\
|
||||
ff_2009_04_21_03_FACTURARE.sql:11-50`; nu a mai fost modificata in `SCRIPTURI_CLAR`, deci pare
|
||||
stabila de atunci):
|
||||
```
|
||||
utilizatori_rol_intern a
|
||||
left join politici_grupuri b on a.id_grup=b.id_grup
|
||||
left join crm_politici_preturi c on b.id_politica=c.id_pol
|
||||
left join crm_politici_pret_art d on b.id_politica=d.id_pol
|
||||
left join nom_articole e on d.id_articol=e.id_articol -- doar um/denumire/codmat/codbare/in_stoc
|
||||
left join crm_note_vanzari f on c.id_nota=f.id_nota
|
||||
left join note_contabile g on f.id_set=g.id_set
|
||||
where ... and d.id_pol is not null -- <- gate-ul, vezi A2
|
||||
```
|
||||
Coloane expuse: `id_pol, preturi_cu_tva, nume_lista_preturi, id_articol, pret, discount_unitar,
|
||||
proc_tvav, um, denumire, codmat, codbare, gestionabil, id_valuta, in_valuta, nota_discount`. **Nicio
|
||||
coloana `cont`.**
|
||||
|
||||
**`ID_JTVA_COLOANA`**: nu apare deloc in `cursor_preturi`. Grep pe tot pachetul arata ca se
|
||||
foloseste doar mai tarziu, la scriere/postare (`scrie_in_vanzari`, `descarca_gestiune`,
|
||||
`contabilizeaza_tva`, in jur de liniile 3700-4130, 4660-5400, 12250-13700 din pachet) — deci cota de
|
||||
TVA "oficiala" (coloana `JTVA_COLOANE`) se rezolva separat de `PROC_TVAV`-ul afisat la selectarea
|
||||
pretului, probabil prin cautare dupa procent in `citeste_id_jtva_coloana`-tip logica (nu am urmarit
|
||||
in detaliu — in afara bugetului A, marcat ca zona neexplorata).
|
||||
|
||||
**Cont de vanzare, de fapt**: parametrul `V_CONT` din `PACK_FACTURARE.adauga_articol_factura`
|
||||
(`:4972-4998`) e trimis de VFP la adaugarea liniei (valoare `'XXXX'` = "fara override" -> `V_CONT2`
|
||||
ramane NULL). Nu am gasit el sa fie citit din `CRM_POLITICI_PRET_ART`/`NOM_ARTICOLE` in acest flux;
|
||||
in schimb exista deja `initializeaza_date_gestiune(V_ID_GESTIUNE, V_ID_TIPGEST, V_CONT, V_ACONT)`
|
||||
(spec `:311-314`) care leaga contul de **gestiune**, nu de articol/politica. Separat, pachetul
|
||||
`PACK_PRETURI` (editorul din ROAPRETURI) scrie `NOM_ARTICOLE.CONT` direct la
|
||||
`adauga_articol`/`modifica_articol` (`D:\ROA\DATABASE\SCRIPTURI\2008\7\ff_2008_07_31_01_PRETURI.sql
|
||||
:107-130, 300-330, 386-424`) — deci **contul de vanzare al articolului exista deja pe
|
||||
`NOM_ARTICOLE.CONT`** (= `catalog_articole.cont` din nomenclatura curenta), independent de orice
|
||||
lista de preturi. Asta inseamna ca, pentru #12, contul NU are nevoie de fallback nou — poate fi citit
|
||||
direct din nomenclator, exact ce cere planul (ramane de confirmat unde/cum VFP populeaza azi `V_CONT`
|
||||
la trimiterea catre `adauga_articol_factura`, cautare separata, in afara bugetului acestei runde).
|
||||
|
||||
### A2. Fallback existent — **NU exista**. Detaliat mai sus (rezumat) si in A1
|
||||
(`d.id_pol is not null`, zero hit-uri `catalog_articole` in `PACK_FACTURARE`). Singurul loc unde
|
||||
`NOM_ARTICOLE`/nomenclatorul intra in calculul de pret e ca sursa a campurilor descriptive
|
||||
(um/denumire/codmat/codbare/in_stoc), niciodata pentru pret/valuta/tva/cont.
|
||||
|
||||
### A3. `citeste_setari_pol_pret` (`:2025-2065`)
|
||||
Nu seteaza `pret_cu_tva`/TVA. Citeste doar **care politica e implicita** pentru un `V_ID_UTIL`, in
|
||||
functie de `V_TIP`: `OPTIUNI.VARNAME` = `'ID_POL_PRET_TR'` (tip 23/30/41), `'ID_POL_PRET_STOC'`
|
||||
(tip 1), `'IDPOLPRETFACTK'` (tip 48/49), fiecare cu `LEFT JOIN CRM_VPOLPRETCURUTIL B ON ... AND
|
||||
B.ID_UTIL=V_ID_UTIL`. Deci `pret_cu_tva`/TVA vin exclusiv din randurile `crm_politici_preturi`/
|
||||
`crm_politici_pret_art` selectate ulterior de `cursor_preturi`, nu din aceasta procedura.
|
||||
|
||||
### A4. Tabelele politicii de pret (coloane confirmate din uz + din
|
||||
`ff_2008_07_31_01_PRETURI.sql:10-95`, ADD/FK, si `create or replace view vcrm_politici_preturi`):
|
||||
|
||||
- **`CRM_POLITICI_PRETURI`**: `ID_POL, NUME_LISTA_PRETURI, DATAI, DATAS, ID_VALUTA, ID_UTIL,
|
||||
DATAORA, NOTA_ONLINE, ID_NOTA, PRETURI_CU_TVA, ID_SUCURSALA, STERS`. FK: `ID_VALUTA->NOM_VALUTE`,
|
||||
`ID_NOTA->CRM_NOTE_VANZARI`, `ID_SUCURSALA->CONTAFIN_ORACLE.NOM_FIRME`.
|
||||
- **`CRM_POLITICI_PRET_ART`**: `ID_POL, ID_ARTICOL, ID_VALUTA, PRET, PRETFTVA, PRETCTVA, PROC_TVAV,
|
||||
DISCOUNT_UNITAR, STERS` (din `modificare_politica_stoc`, `:2105-2119`, si din selectii). **Nicio
|
||||
coloana CONT.**
|
||||
- Nu am gasit `CREATE TABLE` originar pentru aceste doua tabele in `SCRIPTURI_CLAR` (probabil
|
||||
create inainte de 2006, in afara arhivei "clare"); coloanele de mai sus sunt derivate din uz activ
|
||||
in cod, nu dintr-un DDL complet — de tratat ca aproape sigure, nu 100% exhaustive (pot exista
|
||||
coloane suplimentare needitate de codul cercetat).
|
||||
- View-uri asociate: `VCRM_POLITICI_PRETURI` (`ff_2008_07_31_01_PRETURI.sql:42-65`),
|
||||
`VPOLITICI_GRUPURI` (`:67-95`), `CRM_VPOLPRETCURUTIL` (folosit pretutindeni, definitia lui nu a
|
||||
fost cautata — in afara bugetului).
|
||||
|
||||
---
|
||||
|
||||
## B. Cine mai foloseste listele de preturi
|
||||
|
||||
- **ROAFACTURARE**: doar citeste. `crm_vpolpretcurutil` la `COMUN\clase\baza.vc2:10087,10157,
|
||||
10502-10512` (filtrare politici dupa dreptul utilizatorului); `facturare_lista_de_preturi` =
|
||||
`Do politica.mpr` (`COMUN\programe\oproceduri_facturare.prg:113-116`); rapoarte grupate pe
|
||||
`nume_lista_preturi` din `vvanzari_detalii` (`COMUN\clase\configurare.vc2:3915-3972`).
|
||||
(Sursa: `docs\plan_11_integrare_politici_preturi.md:15-22`, deja in `D:\ROA\ROAFACTURARE\docs\`.)
|
||||
- **ROAPRETURI** (`D:\ROA\ROAPRETURI`, exe separat `roapreturi.exe`): **editeaza** politicile —
|
||||
`Clase\opreturi.vcx`, `Clase\onom_preturi.vcx`, `Clase\ofundal_preturi.vcx`,
|
||||
`Programe\update_preturi.prg`, `Programe\update_nomenclator.prg`. Pachet Oracle `PACK_PRETURI`
|
||||
(`adauga_articol`/`modifica_articol`/`verifica_articol` — scriu si pe `NOM_ARTICOLE`, nu doar pe
|
||||
politica). **Nu are cache text (.vc2/.sc2) generat** — nu s-a putut inspecta clasa in detaliu (vezi
|
||||
C4); confirmat prin `Glob D:\ROA\ROAPRETURI\**\*.vc2` = 0 fisiere, doar `.vcx` binare.
|
||||
- **ROACONTRACTE** (`D:\ROA\ROACONTRACTE\Clase\ferestre_contracte.vc2`): citeste direct
|
||||
`vcrm_politici_preturi` / `vcrm_politici_pret_art` prin SQL Pass Through (`goExecutor.oExecute`),
|
||||
la cautarea/atasarea unui articol pe linie de contract
|
||||
(`Programe\oproceduri_roacontracte.prg:213-239`: `select id_pol,... from vcrm_politici_preturi`,
|
||||
apoi `select id_articol, id_pol_art, ... from ]+gcS+[.vcrm_politici_pret_art where id_pol=...`).
|
||||
Nu editeaza politica insasi, doar o consuma pentru a atasa articole+pret pe contract.
|
||||
- **ROAGEST**: 0 hit-uri directe pe `CRM_POLITICI_PRET*`/`cursor_preturi`/`PACK_PRETURI` in cod VFP
|
||||
(`.vc2`/`.prg`) — foloseste probabil acelasi `PACK_FACTURARE` server-side prin
|
||||
`Programe\ofactureaza.prg` (fisier gasit la cautarea `id_pol`, dar doar in comentarii vechi de
|
||||
schema cursor, nu apel activ identificat in bugetul alocat).
|
||||
- **ROAACNPRO**: la fel, 0 hit-uri directe; `id_pol` apare doar intr-un `Text To lcSchema`/
|
||||
`lcSelect` ascuns (`Omitted long matching line` — continut necunoscut, de investigat separat daca
|
||||
devine relevant).
|
||||
- **ROAIMOB**: 0 hit-uri (`.vc2`).
|
||||
- **COMUNROA**: 0 hit-uri (`.vc2`) — surprinzator pentru un modul "CRM transversal"; posibil ca
|
||||
accesul se face exclusiv server-side (proceduri Oracle), nu prin VFP direct in produsele
|
||||
verificate, sau ROAGEST/ROAACNPRO folosesc cod VFP montat din `COMUN` (acelasi `ocomenzi.vcx` etc.)
|
||||
fara sa atinga politica de pret local.
|
||||
- **Nomenclatorul comun** (`update_nomenclator.prg` in ROAPRETURI) scrie in tabela de articole
|
||||
folosita de toate produsele — punct de atentie deja notat in `plan_11...md:82-84` (S2, perimetru).
|
||||
|
||||
**Concluzie B**: politica de pret (structura de date) e deja un modul transversal minim
|
||||
(ROAFACTURARE citeste, ROAPRETURI editeaza, ROACONTRACTE citeste), consistent cu ce spune deja
|
||||
`plan_11...md`. Nu s-a gasit inca un al patrulea consumator activ in cod VFP (ROAGEST/ROAACNPRO
|
||||
probabil trec prin acelasi `PACK_FACTURARE` server-side, fara sa atinga tabelele direct din VFP).
|
||||
|
||||
---
|
||||
|
||||
## C. Incarcare lazy si cautare
|
||||
|
||||
### C1. Cum incarca azi paginile mari
|
||||
|
||||
- **`ct_comenzi`** (`COMUN\clase\ocomenzi.vc2`): montat ca `Page5.Ct_comenzi1`
|
||||
(`Clase\ofundal_facturare.vc2:604-606`). `PROCEDURE Page5.Activate` (`:1006-1008`) apeleaza
|
||||
`this.ct_comenzi1.do_activeaza_container()`. Aceasta e mostenita din `_ct_base.vc2:278-281`
|
||||
(`do_activeaza_container` → `bind keypress` + `This.actualizeaza_cursoare()`).
|
||||
`ocomenzi.actualizeaza_cursoare` (`:1088-1104`) **nu incarca date** — creeaza doar structura
|
||||
cursorului prin `creeaza_cursoare()` (`:1191-1245`), cu `lcFiltru = [id_comanda = -9999999]`
|
||||
(`:1216`) — deci 0 randuri reale la deschidere/activare de pagina.
|
||||
- **`onom_articole.vc2`**: editorul de articol individual (`PROCEDURE Init`, `:1704-1772`) e per-
|
||||
inregistrare (`toRec`), nu o grila; incarca doar cursoarele mici de grupe/subgrupe pentru combo-uri
|
||||
(`crs_grupe_art`, `crs_subgrupe_art`, `:1717-1729`). Nu s-a gasit/verificat in bugetul alocat cum
|
||||
se incarca lista/grila principala de articole a nomenclatorului (formularul-parinte, nu editorul) —
|
||||
**neacoperit**, marcat ca zona pentru o runda ulterioara daca devine relevanta pentru #12/#11.
|
||||
|
||||
### C2. Sablon de lazy loading existent — **DA**, detaliat in rezumat.
|
||||
Cheia: `_ct_base.do_activeaza_container` (hook legat de `Page.Activate`) → `actualizeaza_cursoare()`
|
||||
**suprascrisa** in clasa concreta cu un guard `!Used(cursor) Or <context s-a schimbat>` →
|
||||
`creeaza_cursoare()` cu `WHERE` fals → date reale doar la `do_cauta()`. `_ct_base` insusi ofera doar
|
||||
stub-uri goale (`:231-232` pentru `actualizeaza_cursoare`, la fel `do_adauga/do_cauta/...` la
|
||||
`:283-322`) — **fiecare container concret trebuie sa implementeze explicit lazy-load-ul**, nu vine
|
||||
gratis din mostenire.
|
||||
|
||||
### C3. Cautare server-side vs. filtrare locala
|
||||
- **Server-side (tiparul de urmat)**: `ocomenzi.do_cauta` (`:1484-1510`) construieste `lcFiltru`
|
||||
(`id_sectie = ...` + `filtru_pretty`) si il trimite prin `actualizeaza_grid1(lcFiltru)` →
|
||||
`pocomenzi.ca_baza1.cfiltru=lcFiltru` → `pocomenzi.ca_baza1.afisare()` (`:1109-1123`) — clasa
|
||||
`ca_baza1` (generata de `gencursor`) trimite `WHERE`-ul catre Oracle prin `goExecutor`, nu
|
||||
filtreaza un cursor deja incarcat integral.
|
||||
- **Local (contra-exemplu)**: `actualizeaza_grid1` in continuare (`:1119-1124`) face si operatii pur
|
||||
locale pe cursor deja adus (`SELECT * FROM crscomenzi WITH (Buffering=.T.) WHERE selectat=1 INTO
|
||||
CURSOR crstempcomenzi`) — dar asta e pentru pastrarea selectiei intre reincarcari, nu pentru
|
||||
cautare/filtrare initiala.
|
||||
|
||||
### C4. ROAPRETURI / ROACONTRACTE — incarca tot la deschidere?
|
||||
|
||||
- **ROAPRETURI**: **nu se poate stabili** — lipseste cache-ul text (`.vc2`/`.sc2`), doar `.vcx`
|
||||
binare (`Clase\opreturi.vcx`, `Clase\ofundal_preturi.vcx`); conform regulilor primite, nu am
|
||||
convertit nimic. Precondiitia e deja documentata ca blocanta in `plan_11...md:66-70` (S1: inrolare
|
||||
in fluxul text, procedura `COMUN\docs\inrolare-proiect-git-text.md`).
|
||||
- **ROACONTRACTE**: `ferestre_contracte.vc2` are cache text si e vizibil. Descoperire importanta:
|
||||
clasa container `ct_contracte` (`:9`, `DEFINE CLASS ct_contracte AS _ctfrmbase OF
|
||||
"..\comun\clase\_ct_base.vcx"`) **mosteneste acelasi `_ct_base`** ca `ct_comenzi`, si are propriul
|
||||
`filtru_pretty`/`but_start_criterii1` (vazut in `But_reset_criterii1.Click`, `:1551-1567`) — deci
|
||||
infrastructura de cautare exista. **Dar nu suprascrie `actualizeaza_cursoare`/`creeaza_cursoare`**
|
||||
(0 hit-uri in fisier) — inseamna ca foloseste stub-ul gol din `_ct_base` pentru acel hook, iar
|
||||
cursorul principal (`cContracte`, vazut deja populat la `PROCEDURE Init` a ferestrei,
|
||||
`:1518-1527`, `Select cContracte / If Reccount()>0`) se incarca **altundeva, probabil eager, la
|
||||
deschiderea formularului** — nu s-a gasit punctul exact de populare in bugetul alocat (cautare
|
||||
separata necesara: `cContracte` INTO CURSOR / gencursor pentru contracte). **Concluzie: ROACONTRACTE
|
||||
NU e azi lazy**, desi are "schela" pentru a deveni (acelasi `_ct_base`). Pentru #10/#11, sablonul
|
||||
de copiat e strict cel din `ocomenzi.vc2`, nu cel din `ferestre_contracte.vc2`.
|
||||
|
||||
---
|
||||
|
||||
## Neacoperit / de reluat intr-o runda viitoare
|
||||
- `CRM_VPOLPRETCURUTIL` — definitia view-ului (coloane exacte, drepturi).
|
||||
- `ID_JTVA_COLOANA` — cum se leaga procentul afisat in `cursor_preturi` (`PROC_TVAV`) de coloana TVA
|
||||
oficiala folosita la postare.
|
||||
- Unde/cum populeaza azi VFP parametrul `V_CONT` la `adauga_articol_factura` (ipoteza: din gestiune,
|
||||
nu din articol) — relevant pentru a confirma daca planul #12 poate refolosi direct
|
||||
`NOM_ARTICOLE.CONT` fara alta lucrare.
|
||||
- Incarcarea listei/grilei principale de articole din `onom_articole.vc2` (formularul-parinte, nu
|
||||
editorul per-inregistrare).
|
||||
- Unde exact se populeaza `cContracte` in `ferestre_contracte.vc2` (cautare punctuala, nu facuta).
|
||||
- ROAGEST/ROAACNPRO: confirmarea ca folosesc `PACK_FACTURARE` exclusiv server-side pentru preturi
|
||||
(ipoteza, nu verificata prin citirea completa a `ofactureaza.prg`/`proceduri_acnpro.prg`).
|
||||
110
docs/cercetare/rec_s10_s12.md
Normal file
110
docs/cercetare/rec_s10_s12.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# S10 + S12 — versiune_db.txt, curatare VERSIUNE, propunere changelog 2.11.13
|
||||
|
||||
## S10 — `versiune_db.txt`
|
||||
|
||||
Regula exacta, confirmata in `COMUN\docs\scripturi-migrare-db.md` ("Numerotare si versiune_db.txt"):
|
||||
in `versiune_db.txt` se trece **doar versiunea ultimului script `ff_`** (nu `co_`/`sys_`/`rf_`/`ris_`),
|
||||
pentru ca programele se conecteaza pe schema firmei, nu pe `CONTAFIN_ORACLE`.
|
||||
|
||||
Verificat pe disc, `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\`: cinci scripturi `ff_2026_08_06_*`
|
||||
aplicate azi pe `MARIUSM_AUTO` — `_02` (`PACK_FACTURARE`, S4), `_03` (`PACK_FACTURARE`, S7), `_04`
|
||||
(`VANZARI_COMANDA_CONTRACT`, S6), `_05` (`FACT_VFACTURI`, S8), `_06` (`VANZARI_BACKFILL`, S5).
|
||||
Confirmat si prin interogare pe `VERSIUNE` (`order by data_script desc, seq_script desc`): ultimul
|
||||
`ff_` aplicat e `ff_2026_08_06_06_COMUN_VANZARI_BACKFILL.sql`.
|
||||
|
||||
**Scris in `versiune_db.txt`: `2026_08_06_06`** (fara newline la final, pastrand conventia
|
||||
fisierului existent — verificat byte-level, 13 octeti, identic ca lungime cu vechea valoare
|
||||
`2026_08_02_01`).
|
||||
|
||||
## S10 — starea tabelei `VERSIUNE`
|
||||
|
||||
Interogata direct pe `MARIUSM_AUTO` (`docs\cercetare\s10_curata_versiune.sql`, pasul 1). Numar de
|
||||
inregistrari per script, azi:
|
||||
|
||||
| Script | Inregistrari |
|
||||
|---|---|
|
||||
| `ff_2026_08_06_02_COMUN_PACK_FACTURARE.sql` (S4) | 2 |
|
||||
| `ff_2026_08_06_03_COMUN_PACK_FACTURARE.sql` (S7) | 1 |
|
||||
| `ff_2026_08_06_04_COMUN_VANZARI_COMANDA_CONTRACT.sql` (S6) | 2 |
|
||||
| `ff_2026_08_06_05_COMUN_FACT_VFACTURI.sql` (S8) | 4 |
|
||||
| `ff_2026_08_06_06_COMUN_VANZARI_BACKFILL.sql` (S5) | 5 |
|
||||
|
||||
14 randuri in total pentru cele 5 scripturi de azi, 9 in plus fata de cate 1 per script. Confirma
|
||||
tiparul semnalat: `_02`, `_05`, `_06` (si, in plus fata de ce era asteptat, `_04`) au fost aplicate
|
||||
de mai multe ori pe masura extinderii lor in cursul zilei; `_03` are deja un singur rand, nimic de
|
||||
curatat acolo.
|
||||
|
||||
**Propunere, nerulata**: `docs\cercetare\s10_curata_versiune.sql`. Pastreaza per script randul cu
|
||||
`ID_VERSIUNE` maxim (ultima aplicare = starea finala reala a scriptului), sterge restul — scoped
|
||||
strict pe cele 5 nume de script din lista de mai sus, cu `select` de verificare inainte si dupa,
|
||||
`delete` la mijloc, `commit` comentat (de dat manual). Fara impact functional indiferent daca se
|
||||
ruleaza sau nu: nici `versiune_db.txt`, nici aplicarea DDL nu depind de numarul de randuri din
|
||||
`VERSIUNE`. **Nu s-a rulat** — stergerea de istoric ramane decizie de om.
|
||||
|
||||
## S12 — propunere changelog
|
||||
|
||||
Livrat: `docs\propunere_changelog_2.11.13.txt` (neaplicat in `changelog_roafacturare.txt`).
|
||||
|
||||
```
|
||||
<!--
|
||||
06/08/2026
|
||||
ROAFACTURARE - 2.11.13
|
||||
|
||||
:eroare:
|
||||
Referinta catre aviz de pe facturi era gresita - toate facturile aratau acelasi aviz, indiferent de cel real. Acum se afiseaza avizul corect acolo unde exista, iar unde nu exista referinta, campul ramane necompletat.
|
||||
|
||||
Unele facturi mai vechi ramasesera fara total salvat la emitere si aparea fara valoare la listare sau retiparire. Totalurile lipsa au fost completate.
|
||||
|
||||
Cursul valutar afisat pe facturile emise in lei era uneori inregistrat gresit. Facturile in lei nu mai afiseaza curs valutar strain.
|
||||
|
||||
La facturile de retur-transfer numele clientului afisat in lista de facturi era uneori gresit. Acum se afiseaza clientul corect.
|
||||
|
||||
:modificare:
|
||||
S-a uniformizat textul explicativ (comanda/contract) afisat pe facturi.
|
||||
-->
|
||||
```
|
||||
|
||||
### Motivare inclusiune/excludere
|
||||
|
||||
- **Aviz, totaluri, curs valutar** (`:eroare:`) — toate trei sunt defecte confirmate ca fiind
|
||||
efectiv pe date de productie (`VENDING`), vizibile pe facturi reale (lista principala si
|
||||
retiparire), acum corectate. Se incadreaza clar la `:eroare:`.
|
||||
- **`CLIENT` pe retur-transfer** (`:eroare:`) — `fact_vfacturi`, folosit de gridul principal de
|
||||
listare, calcula gresit numele clientului pe cele 23 de facturi `tip=41`/`tip=-6`; view-ul
|
||||
corect (`fact_vfacturi2`) confirma sursa deliberata din cod. E o valoare gresita afisata in
|
||||
productie, nu doar o diferenta cosmetica intre doua liste — de aceea l-am pus la `:eroare:` si
|
||||
nu la `:modificare:`, desi in mesajul initial parea doar "etichete neuniforme".
|
||||
- **`EXPLICATIE`** (`:modificare:`) — diferenta e strict de formatare a textului
|
||||
("COMERCIAL - FACTURARE" vs "COMERCIAL-FACTURARE" etc.), nu o valoare gresita; l-am tinut separat
|
||||
si mai jos in prioritate, la `:modificare:`.
|
||||
- **Denormalizarea comanda/contract (S6) — EXCLUSA din changelog.** Harnessul de regresie da
|
||||
aceleasi cifre inainte si dupa aplicarea scriptului; nu exista nimic vizibil pentru utilizator.
|
||||
O intrare de changelog ar fi inselatoare (ar sugera o schimbare functionala inexistenta).
|
||||
- **Incasarea lipsa pe facturile din devize auto — EXCLUSA din `changelog_roafacturare.txt`.**
|
||||
Corectia e integral in cod VFP din **ROAAUTO** (`Programe\oproceduri_devize.prg`,
|
||||
`factureaza_deviz`) plus un parametru nou cu `DEFAULT` in `PACK_FACTURARE.scrie_incasari`
|
||||
(pachet Oracle comun, dar ramura noua e apelata **doar** din ROAAUTO). Recompilarea
|
||||
`roafacturare.exe` singura, fara recompilarea ROAAUTO, nu produce niciun efect vizibil pentru
|
||||
utilizatorul ROAFACTURARE — deci intrarea nu apartine acestui changelog, chiar daca facturile
|
||||
respective ar putea fi vazute si din listele ROAFACTURARE dupa ce ROAAUTO e recompilat si el.
|
||||
**Propunere de text pentru `changelog_roaauto.txt` (needitat, doar propus aici)**:
|
||||
|
||||
```
|
||||
<!--
|
||||
06/08/2026
|
||||
ROAAUTO - 2.5.5
|
||||
|
||||
:eroare:
|
||||
La facturile emise din deviz auto nu se inregistra incasarea (chitanta/bon), desi factura era platita. S-a corectat.
|
||||
-->
|
||||
```
|
||||
|
||||
## Fisiere livrate
|
||||
|
||||
- `versiune_db.txt` — actualizat la `2026_08_06_06` (editat direct, marcaj de proiect).
|
||||
- `docs\cercetare\s10_curata_versiune.sql` — propunere de curatare, **nerulata**.
|
||||
- `docs\propunere_changelog_2.11.13.txt` — propunere, **neaplicata** in `changelog_roafacturare.txt`.
|
||||
- Acest raport.
|
||||
|
||||
**Fara commit** (git/SVN). Nu s-au atins scripturile de migrare, nu s-a rulat DDL, nu s-a scris in
|
||||
`VERSIUNE`.
|
||||
780
docs/cercetare/rec_s5_proiectare_oracle.md
Normal file
780
docs/cercetare/rec_s5_proiectare_oracle.md
Normal file
@@ -0,0 +1,780 @@
|
||||
# Cercetare S5 — proiectarea partii Oracle (plan #6, editare factura emisa)
|
||||
|
||||
Data: 09.08.2026. Sursa: export PROASPAT din `MARIUSM_AUTO@ROA_CENTRAL` (`all_source`), facut in
|
||||
aceasta sesiune, in scratchpad (nu in proiect):
|
||||
|
||||
- `PACK_FACTURARE.pck` — 16160 linii
|
||||
- `PACK_CONTAFIN.pck` — 8550 linii
|
||||
|
||||
**Toate numerele de linie de mai jos sunt din ACEST export.** Raportul precedent
|
||||
(`rec_s5_oracle_vanzari.md`, 08.08.2026) declara `PACK_FACTURARE.pck = 17010` linii; offset-urile
|
||||
procedurilor coincid totusi exact (`scrie_in_vanzari` la `:13491`, `actualizeaza_vanzari` la
|
||||
`:16015`), deci diferenta e de formatare a spool-ului, nu de continut. Concluziile lui A.1-A.2, C si
|
||||
D raman valabile pe sursa de azi si nu se repeta aici.
|
||||
|
||||
**Doua corectii de fond fata de raportul precedent** (detaliate la 3 si 4):
|
||||
|
||||
1. agregarea NU citeste `VANZARI_SETURI_TEMP`, ci tabela **persistenta `VANZARI_SETURI`**
|
||||
(`:13916`) — deci liniile de set se pot reconstitui integral la editare;
|
||||
2. recomandarea „procedura noua apelata din interiorul `finalizeaza_modificare_nota`" e
|
||||
**incompatibila cu ordinea corecta de scriere** si trebuie abandonata.
|
||||
|
||||
---
|
||||
|
||||
## 1. Baza de plecare e la zi? DA (pentru `ff_`)
|
||||
|
||||
Comparatie `VERSIUNE` (4151 randuri) vs. `D:\ROA\DATABASE\SCRIPTURI_CLAR` (3030 fisiere `.sql`):
|
||||
|
||||
- **`ff_` pe disc dar neaplicate in `MARIUSM_AUTO`: 0.** Schema e la zi pe tot ce o priveste.
|
||||
- Ultimul `ff_` inregistrat: `ff_2026_08_08_01_COMUN_VVANZARI_ARTICOLE.sql`, identic cu
|
||||
`versiune_db.txt` din radacina proiectului (`2026_08_08_01`).
|
||||
- Cele 26 de scripturi din 2026 care lipsesc din `VERSIUNE` sunt **exclusiv `co_` si `sys_`** — se
|
||||
aplica pe `CONTAFIN_ORACLE`, respectiv `SYS`, nu pe schema firmei; `VERSIUNE` din `MARIUSM_AUTO`
|
||||
contine doar 3 randuri `co_`, deci absenta lor e normala, nu o restanta.
|
||||
|
||||
**Verdict: se poate construi propunerea peste sursa exportata azi.**
|
||||
|
||||
### Doua anomalii de semnalat (nu blocheaza S5)
|
||||
|
||||
- **`ff_2026_08_08_01_COMUN_VVD_TOT.sql` e inregistrat in `VERSIUNE` dar NU exista nicaieri pe
|
||||
disc** (cautat recursiv in tot `SCRIPTURI_CLAR`). Un obiect aplicat in dev fara script salvat nu
|
||||
ajunge niciodata la clienti. De verificat cu Marius daca e un script de lucru abandonat sau daca
|
||||
lipseste din SVN.
|
||||
- Acelasi `NN` (`2026_08_08_01`) e folosit de doua scripturi `ff_` (`VVANZARI_ARTICOLE` si
|
||||
`VVD_TOT`), contra regulii „NN e secventa unica pe zi".
|
||||
|
||||
---
|
||||
|
||||
## 2. Blocul de agregare din `scrie_in_vanzari` — integral
|
||||
|
||||
Procedura: `PACK_FACTURARE.pck:13491-13956`. Blocul de agregare + `UPDATE VANZARI` e
|
||||
`:13762-13954`, citat integral:
|
||||
|
||||
```
|
||||
13762 -- Completare totaluri in vanzari din vanzari_detalii pentru a usura selectiile din fact_vfacturi
|
||||
13763 begin
|
||||
13764 select DISC_TVA_VAL AS DISCOUNT_TVA,
|
||||
13765 VALOARE_ACHIZITIE,
|
||||
13766 a.suma_fara_tva_ron - a.disc_fara_tva_ron as TOTAL_FARA_TVA,
|
||||
13767 a.suma_tva_ron - a.disc_tva_ron as TOTAL_TVA,
|
||||
13768 a.suma_fara_tva_ron - a.disc_fara_tva_ron + a.suma_tva_ron -
|
||||
13769 a.disc_tva_ron as TOTAL_CU_TVA,
|
||||
13770 a.suma_fara_tva_val - a.disc_fara_tva_val as VALVAL,
|
||||
13771 a.suma_tva_val - a.disc_tva_val as TVAVAL,
|
||||
13772 a.suma_fara_tva_val - a.disc_fara_tva_val + a.suma_tva_val -
|
||||
13773 a.disc_tva_val as TOTVAL,
|
||||
13774 id_valuta,
|
||||
13775 curs,
|
||||
13776 multiplicator,
|
||||
13777 pack_facturare.cserie_act_incasare as SERIE_INCASAT,
|
||||
13778 pack_facturare.nnumar_act_incasare as NR_INCASAT,
|
||||
13779 pack_facturare.nsuma_incasare AS SUMA_INCASAT,
|
||||
13780 pack_facturare.ntip_doc_incasare as TIP_INCASAT
|
||||
13781 INTO lnDiscountTVA,
|
||||
13782 lnValoareAchizitie,
|
||||
13783 lnTotalFaraTVA,
|
||||
13784 lnTotalTVA,
|
||||
13785 lnTotalCuTVA,
|
||||
13786 lnValVal,
|
||||
13787 lnTVAVal,
|
||||
13788 lnTotVal,
|
||||
13789 lnIdValuta,
|
||||
13790 lnCurs,
|
||||
13791 lnMultiplicator,
|
||||
13792 lnSerieIncasat,
|
||||
13793 lnNrIncasat,
|
||||
13794 lnSumaIncasat,
|
||||
13795 lnTipIncasat
|
||||
13796 FROM (select MAX(decode(pack_facturare.nin_valuta,
|
||||
13797 1,
|
||||
13798 ROUND(a1.curs * NVL(V_DISCOUNT_FACTURA, 0) /
|
||||
13799 a1.multiplicator,
|
||||
13800 lnPreciziePretV),
|
||||
13801 NVL(V_DISCOUNT_FACTURA, 0))) as DISC_FARA_TVA_RON,
|
||||
13802 NVL(V_DISCOUNT_FACTURA, 0) as DISC_FARA_TVA_VAL,
|
||||
13803 pack_facturare.nin_valuta AS IN_VALUTA,
|
||||
13804 MAX(ROUND(decode(pack_facturare.nin_valuta,
|
||||
13805 1,
|
||||
13806 ROUND(a1.curs *
|
||||
13807 NVL(V_DISCOUNT_FACTURA, 0) /
|
||||
13808 a1.multiplicator,
|
||||
13809 lnPreciziePretV),
|
||||
13810 NVL(V_DISCOUNT_FACTURA, 0)) *
|
||||
13811 (a1.proc_tvav - 1),
|
||||
13812 lnPreciziePretV)) as DISC_TVA_RON,
|
||||
13813 MAX(ROUND(NVL(V_DISCOUNT_FACTURA, 0) *
|
||||
13814 (a1.proc_tvav - 1),
|
||||
13815 lnPreciziePretV)) as DISC_TVA_VAL,
|
||||
13816 sum(pack_facturare.calculeaza_total_fara_tva_fact(a1.pret_ron,
|
||||
13817 0,
|
||||
13818 1,
|
||||
13819 NVL(a1.discount_unitar_ron,
|
||||
13820 0),
|
||||
13821 pack_facturare.ndiscount_evidentiat,
|
||||
13822 a1.cantitate,
|
||||
13823 a1.pret_cu_tva,
|
||||
13824 a1.proc_tvav)) AS SUMA_FARA_TVA_RON,
|
||||
13825 sum(pack_facturare.calculeaza_total_tva_fact(a1.pret_ron,
|
||||
13826 0,
|
||||
13827 1,
|
||||
13828 NVL(a1.discount_unitar_ron,
|
||||
13829 0),
|
||||
13830 pack_facturare.ndiscount_evidentiat,
|
||||
13831 a1.cantitate,
|
||||
13832 a1.pret_cu_tva,
|
||||
13833 a1.proc_tvav)) as SUMA_TVA_RON,
|
||||
13834 sum(pack_facturare.calculeaza_total_fara_tva_fact(a1.pret_val,
|
||||
13835 0,
|
||||
13836 1,
|
||||
13837 NVL(a1.discount_unitar_val,
|
||||
13838 0),
|
||||
13839 pack_facturare.ndiscount_evidentiat,
|
||||
13840 a1.cantitate,
|
||||
13841 a1.pret_cu_tva,
|
||||
13842 a1.proc_tvav)) AS SUMA_FARA_TVA_VAL,
|
||||
13843 sum(pack_facturare.calculeaza_total_tva_fact(a1.pret_val,
|
||||
13844 0,
|
||||
13845 1,
|
||||
13846 NVL(a1.discount_unitar_val,
|
||||
13847 0),
|
||||
13848 pack_facturare.ndiscount_evidentiat,
|
||||
13849 a1.cantitate,
|
||||
13850 a1.pret_cu_tva,
|
||||
13851 a1.proc_tvav)) as SUMA_TVA_VAL,
|
||||
13852 sum(round(a1.cantitate * a1.pret_achizitie,
|
||||
13853 lnPrecizieCalcul)) AS VALOARE_ACHIZITIE,
|
||||
13854 max(decode(pack_facturare.nin_valuta, 1, a1.id_valuta, 0)) as id_valuta,
|
||||
13855 max(decode(pack_facturare.nin_valuta, 1, a1.curs, 1)) as curs,
|
||||
13856 max(decode(pack_facturare.nin_valuta, 1, a1.multiplicator, 1)) as multiplicator
|
||||
13857 from (select vd.id_vanzare_set,
|
||||
13858 (case
|
||||
13859 when (pack_facturare.nin_valuta = 1 or
|
||||
13860 vd.id_valuta <>
|
||||
13861 pack_def.GetIdMonedaNationala()) then
|
||||
13862 ROUND(vc.curs * vd.pret / vc.multiplicator,
|
||||
13863 lnPreciziePretV)
|
||||
13864 else
|
||||
13865 vd.pret
|
||||
13866 end) as pret_ron,
|
||||
13867 vd.pret as pret_val,
|
||||
13868 vd.proc_tvav,
|
||||
13869 vd.cantitate,
|
||||
13870 vd.diferenta,
|
||||
13871 (case
|
||||
13872 when (pack_facturare.nin_valuta = 1 or
|
||||
13873 vd.id_valuta <>
|
||||
13874 pack_def.GetIdMonedaNationala()) then
|
||||
13875 ROUND(vc.curs * vd.discount_unitar /
|
||||
13876 vc.multiplicator,
|
||||
13877 lnPreciziePretV)
|
||||
13878 else
|
||||
13879 vd.discount_unitar
|
||||
13880 end) as discount_unitar_ron,
|
||||
13881 vd.discount_unitar as discount_unitar_val,
|
||||
13882 vd.id_valuta,
|
||||
13883 vd.pret_cu_tva,
|
||||
13884 vd.pret_achizitie,
|
||||
13885 vc.curs,
|
||||
13886 vc.multiplicator
|
||||
13887 from (select a.id_vanzare_set,
|
||||
13888 a.pret,
|
||||
13889 a.proc_tvav,
|
||||
13890 a.cantitate,
|
||||
13891 a.diferenta,
|
||||
13892 a.discount_unitar,
|
||||
13893 a.id_valuta,
|
||||
13894 a.pret_cu_tva,
|
||||
13895 a.pret_achizitie
|
||||
13896 from VANZARI_DETALII_TEMP a
|
||||
13897 where nvl(a.id_vanzare_set, 0) = 0
|
||||
13898 union all
|
||||
13899 select b.id_vanzare_set,
|
||||
13900 b.pret,
|
||||
13901 max(c.proc_tvav) as proc_tvav,
|
||||
13902 b.cantitate,
|
||||
13903 0 as diferenta,
|
||||
13904 b.discount_unitar,
|
||||
13905 decode(pack_facturare.nin_valuta,
|
||||
13906 0,
|
||||
13907 pack_def.GetIdMonedaNationala(),
|
||||
13908 c.id_valuta) as id_valuta,
|
||||
13909 b.pret_cu_tva,
|
||||
13910 sum(decode(b.cantitate,
|
||||
13911 0,
|
||||
13912 0,
|
||||
13913 c.pret_achizitie * c.cantitate /
|
||||
13914 b.cantitate)) as pret_achizitie
|
||||
13915 from vanzari_detalii_temp c
|
||||
13916 left join vanzari_seturi b
|
||||
13917 on b.id_vanzare_set = c.id_vanzare_set
|
||||
13918 where nvl(c.id_vanzare_set, 0) <> 0
|
||||
13919 and nvl(pack_facturare.nin_valuta, -1) > -1
|
||||
13920 group by b.id_vanzare_set,
|
||||
13921 b.pret,
|
||||
13922 b.cantitate,
|
||||
13923 b.discount_unitar,
|
||||
13924 b.pret_cu_tva,
|
||||
13925 decode(pack_facturare.nin_valuta,
|
||||
13926 0,
|
||||
13927 pack_def.GetIdMonedaNationala(),
|
||||
13928 c.id_valuta)) vd
|
||||
13929 left join vanzari_cursuri vc
|
||||
13930 on vc.id_vanzare = V_ID_VANZARE
|
||||
13931 and vd.id_valuta = vc.id_valuta) a1) a;
|
||||
13932
|
||||
13933 update vanzari
|
||||
13934 set discount_tva = lnDiscountTVA,
|
||||
13935 valoare_achizitie = lnValoareAchizitie,
|
||||
13936 total_fara_tva = lnTotalFaraTVA,
|
||||
13937 total_tva = lnTotalTVA,
|
||||
13938 total_cu_tva = lnTotalCuTVA,
|
||||
13939 valval = lnValVal,
|
||||
13940 tvaval = lnTVAVal,
|
||||
13941 totval = lnTotVal,
|
||||
13942 id_valuta = lnIdValuta,
|
||||
13943 curs = lnCurs,
|
||||
13944 multiplicator = lnMultiplicator,
|
||||
13945 serie_incasat = lnSerieIncasat,
|
||||
13946 nr_incasat = lnNrIncasat,
|
||||
13947 suma_incasat = lnSumaIncasat,
|
||||
13948 tip_incasat = lnTipIncasat
|
||||
13949 where id_vanzare = V_ID_VANZARE;
|
||||
13950
|
||||
13951 exception
|
||||
13952 when NO_DATA_FOUND then
|
||||
13953 null;
|
||||
13954 end;
|
||||
```
|
||||
|
||||
Variabilele locale relevante, declarate la `:13501-13523`:
|
||||
|
||||
```
|
||||
13522 lnPrecizieCalcul NUMBER(2) := pack_sesiune.getOptiuneFirma('PC');
|
||||
13523 lnPreciziePretV NUMBER(2) := pack_sesiune.getOptiuneFirma('PPRETV');
|
||||
```
|
||||
|
||||
### Inventarul dependentelor blocului
|
||||
|
||||
| Dependenta | Linii | Sursa la emitere | Echivalent PERSISTENT la editare | Verdict |
|
||||
|---|---|---|---|---|
|
||||
| `V_DISCOUNT_FACTURA` | 13798, 13801, 13802, 13807, 13810, 13813 | parametru al procedurii | **`VANZARI.DISCOUNT`** — scrisa la INSERT din exact acelasi parametru (`:13621` / `:13682`) | reconstituibil |
|
||||
| `pack_facturare.nin_valuta` | 13796, 13803, 13804, 13854-13856, 13859, 13872, 13905, 13919, 13925 | stare de sesiune pe pachet | **`VANZARI.IN_VALUTA`** (`NUMBER(1)`, NOT NULL) — scrisa la INSERT din aceeasi variabila (`:13625` / `:13686`) | reconstituibil |
|
||||
| `pack_facturare.ndiscount_evidentiat` | 13821, 13830, 13839, 13848 | stare de sesiune pe pachet | **`VANZARI.DISCOUNT_EVIDENTIAT`** — scrisa la INSERT din aceeasi variabila (`:13622` / `:13683`) | reconstituibil |
|
||||
| `cserie_act_incasare`, `nnumar_act_incasare`, `nsuma_incasare`, `ntip_doc_incasare` | 13777-13780 | stare de sesiune, setata numai in fluxul de emitere (`:13102-13144`; resetate la `:1882-1886`) | **NICIUNUL** | vezi 6 |
|
||||
| `pack_def.GetIdMonedaNationala()` | 13861, 13874, 13907, 13927 | functie pura: `SELECT MIN(ID_VALUTA) FROM NOM_VALUTE WHERE STERS=0 AND MONEDA_NATIONALA=1` (PACK_DEF body `:214-230`) | idem — fara stare | fara probleme |
|
||||
| `pack_sesiune.getOptiuneFirma('PC'/'PPRETV')` | 13522-13523, 13853 | `SELECT varvalue FROM optiuni WHERE ...` (PACK_SESIUNE body `:119-141`) — **lookup pe tabela, fara stare de pachet** | idem | fara probleme |
|
||||
| `VANZARI_DETALII_TEMP` (liniile directe) | 13896-13897 | GTT `ON COMMIT DELETE ROWS` | **`VANZARI_DETALII WHERE ID_VANZARE = :id AND STERS = 0 AND NVL(ID_VANZARE_SET,0) = 0`** | vezi 3 |
|
||||
| `VANZARI_DETALII_TEMP` (liniile de set, alias `c`) | 13915, 13918 | GTT | **`VANZARI_DETALII ... AND NVL(ID_VANZARE_SET,0) <> 0`** | vezi 3 |
|
||||
| `vanzari_seturi` (alias `b`) | 13916 | **tabela PERSISTENTA, deja** | ea insasi | vezi 3 |
|
||||
| `vanzari_cursuri vc` | 13929-13930 | tabela persistenta, populata cu `id_vanzare`-ul curent la `:13704` (`scrie_cursuri`) | ea insasi, deja legata pe `ID_VANZARE` | fara probleme |
|
||||
|
||||
Verificat pe `all_tab_columns`: **toate cele 9 coloane citite din `VANZARI_DETALII_TEMP` de
|
||||
agregare** (`id_vanzare_set, pret, proc_tvav, cantitate, diferenta, discount_unitar, id_valuta,
|
||||
pret_cu_tva, pret_achizitie`) exista, cu acelasi nume, in `VANZARI_DETALII`. Singurele coloane pe
|
||||
care TEMP le are in plus si care nu exista in tabela reala sunt `CURS, MULTIPLICATOR, EXPLICATIA,
|
||||
ID_COMANDA, NUMAR_ACT, ID_TEMP, ID_UTIL, IN_STOC, PRETV_ORIG, ID_GESTIUNE_DEST, ID_LUCRARE_REZ,
|
||||
ID_PART_REZ` — **niciuna nu e folosita de blocul de agregare** (`curs`/`multiplicator` vin din
|
||||
`vanzari_cursuri vc`, nu din linie).
|
||||
|
||||
**Concluzie: blocul se reproduce 1:1 pe surse persistente, schimband doar clauzele `FROM` si
|
||||
inlocuind cele 3 valori de stare cu cele 3 coloane din `VANZARI`.** Nu e nevoie de nicio
|
||||
reformulare a formulei — inclusiv `calculeaza_total_fara_tva_fact` / `calculeaza_total_tva_fact`
|
||||
(`PACK_FACTURARE.pck:15858-16013`, semnaturi in spec la `:1167-1185`) raman apelate identic.
|
||||
|
||||
Doua observatii de detaliu:
|
||||
- `a1.diferenta` e selectata (`:13870`, `:13891`) dar **nu e folosita nicaieri** in agregarea din
|
||||
`scrie_in_vanzari` (parametrul `V_DIFERENTA` e `0` hard-codat la `:13817`, `:13826`, `:13835`,
|
||||
`:13844`). Se poate pastra pentru fidelitate sau elimina; recomand pastrarea, ca diff-ul fata de
|
||||
original sa ramana citibil.
|
||||
- Handler-ul `WHEN NO_DATA_FOUND THEN NULL` (`:13951-13953`) e defensiv si practic inaccesibil:
|
||||
subinterogarea are agregate fara `GROUP BY`, deci intoarce mereu exact un rand. **Dar** pe zero
|
||||
linii agregatele intorc `NULL`, nu `0` — la emitere cazul nu poate aparea, la editare da (vezi
|
||||
riscul R4).
|
||||
|
||||
---
|
||||
|
||||
## 3. Liniile din seturi — EXISTA echivalent persistent
|
||||
|
||||
**Corectia raportului precedent.** Agregarea nu citeste `VANZARI_SETURI_TEMP`, ci
|
||||
**`VANZARI_SETURI`** (`PACK_FACTURARE.pck:13916`), care e o tabela **normala, persistenta**
|
||||
(verificat pe `all_tables`: `VANZARI_SETURI temporary=N`; doar `VANZARI_SETURI_TEMP` si
|
||||
`VANZARI_DETALII_TEMP` sunt `temporary=Y duration=SYS$TRANSACTION`).
|
||||
|
||||
Trecerea TEMP -> persistent o face `pack_facturare.scrie_seturi` (`:13993-14028`), apelata la
|
||||
`:13706`, **inainte** de agregare: insereaza fiecare rand din `VANZARI_SETURI_TEMP` in
|
||||
`VANZARI_SETURI` (`ID_VANZARE_SET` din `SEQ_VANZARI_SETURI`, prin trigger
|
||||
`TRG_VANZARI_SET_BEFOINS`) si reface pointerul in `VANZARI_DETALII_TEMP.ID_VANZARE_SET`. De aceea
|
||||
agregarea de la `:13915-13928` face join intre TEMP (componentele) si tabela persistenta (capul de
|
||||
set).
|
||||
|
||||
Structura `VANZARI_SETURI` (`all_tab_columns`), identica cu a TEMP-ului:
|
||||
|
||||
```
|
||||
ID_VANZARE_SET NUMBER(10) NOT NULL -- PK, din SEQ_VANZARI_SETURI
|
||||
DENUMIRE VARCHAR2(100)
|
||||
EXPLICATIE VARCHAR2(100)
|
||||
CANTITATE NUMBER(10,4)
|
||||
UM VARCHAR2(10)
|
||||
SERIE VARCHAR2(100)
|
||||
PRET NUMBER(20,4)
|
||||
DISCOUNT_UNITAR NUMBER(20,4)
|
||||
PRET_CU_TVA NUMBER(1) NOT NULL
|
||||
```
|
||||
|
||||
Nu are `ID_VANZARE` si nu are `STERS`: legatura cu documentul e **exclusiv** prin
|
||||
`VANZARI_DETALII.ID_VANZARE_SET`. Deci filtrarea pe document se face tot din `VANZARI_DETALII`.
|
||||
|
||||
**Precedent care confirma reconstituirea**: `pack_facturare.citeste_vanzari_seturi`
|
||||
(`:16619-16698`) reface deja exact acest lucru pe surse persistente — `VANZARI` (`cod`, `sters=0`)
|
||||
+ `VANZARI_DETALII` (`sters=0`, `id_vanzare_set is not null`) + `VANZARI_CURSURI` +
|
||||
`VANZARI_SETURI`, cu acelasi `GROUP BY b.id_vanzare_set`. Nu inventam un tipar nou.
|
||||
|
||||
**Raspuns la intrebarea din brief: DA, recalculul poate acoperi si liniile de set, fara pierdere de
|
||||
informatie.** Transformarea necesara in ramura de set:
|
||||
|
||||
```
|
||||
from vanzari_detalii c -- in loc de vanzari_detalii_temp c
|
||||
left join vanzari_seturi b on b.id_vanzare_set = c.id_vanzare_set
|
||||
where nvl(c.id_vanzare_set, 0) <> 0
|
||||
and c.id_vanzare = V_ID_VANZARE
|
||||
and c.sters = 0
|
||||
```
|
||||
|
||||
Date (test, `MARIUSM_AUTO`): 4 randuri in `VANZARI_SETURI`, 4 documente cu linii de set. **Nu e o
|
||||
dovada** — validarea ramane pe cod, nu pe volum.
|
||||
|
||||
### Ce NU se poate face din interfata (limitare de semnalat pentru S4)
|
||||
|
||||
View-ul `VVANZARI_ARTICOLE` (sursa lui `IncarcaArticoleFactura`,
|
||||
`COMUN\programe\ofacturare_editare.prg:288-330`) **nu expune `ID_VANZARE_SET` si nici
|
||||
`PRET_ACHIZITIE`**:
|
||||
|
||||
```
|
||||
select vd.id_vanzare, vd.id_vanzare_det, vd.id_articol, vd.cantitate, vd.pret, vd.pret_cu_tva,
|
||||
vd.proc_tvav, vd.discount_unitar, vd.id_gestiune, vd.cont, vd.id_valuta,
|
||||
vd.id_jtva_coloana, vd.serie, vd.explicatie, vd.taxcode, vd.lot, vd.sters,
|
||||
na.denumire, na.codmat, ng.nume_gestiune, nv.nume_val
|
||||
from vanzari_detalii vd
|
||||
left join nom_articole na on na.id_articol = vd.id_articol
|
||||
left join nom_gestiuni ng on ng.id_gestiune = vd.id_gestiune
|
||||
left join nom_valute nv on nv.id_valuta = vd.id_valuta
|
||||
```
|
||||
|
||||
Consecinte concrete:
|
||||
|
||||
1. componentele de set apar in grid ca linii obisnuite, dar formularul **nu poate sti** ca sunt
|
||||
componente si nu poate edita capul de set (`VANZARI_SETURI.PRET`/`CANTITATE`), care e ceea ce
|
||||
intra efectiv in totaluri. Un utilizator care schimba pretul unei componente **nu schimba
|
||||
totalul documentului** — recalculul ia pretul din `VANZARI_SETURI`. Divergenta tacuta.
|
||||
2. `PRET_ACHIZITIE` lipseste din cursor, deci VFP nu-l poate rescrie la un `UPDATE` de linie: la
|
||||
scriere trebuie **omis din `SET`**, ca sa ramana valoarea existenta (altfel `VALOARE_ACHIZITIE`
|
||||
se pierde). Pentru liniile **noi** insa nu exista sursa — vor intra cu `PRET_ACHIZITIE` NULL si
|
||||
vor contribui cu NULL la `SUM(round(cantitate * pret_achizitie))`, deci **`VALOARE_ACHIZITIE`
|
||||
devine NULL pe tot documentul** daca fie si o singura linie noua are NULL. Vezi riscul R3.
|
||||
|
||||
---
|
||||
|
||||
## 4. Capcana de ordonare — punctul central
|
||||
|
||||
### Ce ruleaza azi, in ce ordine
|
||||
|
||||
Punctul de intrare nou (deja scris in ramura curenta):
|
||||
`COMUN\clase\ofacturare_comun.vc2`, `do_editare_factura`, blocul de salvare:
|
||||
|
||||
```
|
||||
3798 If Thisform.do_deschide_tranzactie() && SQLSetprop(gnHandle,"Transactions",2)
|
||||
3800 lnSucces = OSCRIE_IN_FISIERE(2,.T.,.T.) && marcheaza STERS=1 nota veche
|
||||
...
|
||||
3820 lnSucces = OSCRIE_IN_FISIERE(0,.T.,.T.) && scrie nota noua (COD nou din SCRIE_IN_ACT)
|
||||
3823 If lnSucces > 0
|
||||
3824 lcSql = [begin pack_contafin.finalizeaza_modificare_nota(...); end]
|
||||
3826 lnSucces = Iif(goExecutor.oExecuta(lcSql),1,-1)
|
||||
3827 Endif
|
||||
3828 If Thisform.do_inchide_tranzactie(Iif(lnSucces<0,2,1)) && SQLCOMMIT / SQLROLLBACK
|
||||
```
|
||||
|
||||
`do_deschide_tranzactie` / `do_inchide_tranzactie`: `COMUN\clase\_frm_base.vc2:251-269` si
|
||||
`:278-302` — `SQLSetprop(gnHandle,"Transactions",2)` / `Sqlcommit(gnHandle)`.
|
||||
|
||||
`finalizeaza_modificare_nota` (`PACK_CONTAFIN.pck:8601-8651`) apeleaza `actualizeaza_vanzari` la
|
||||
`:8616`, gardat de `SELECT COUNT(*) FROM vanzari WHERE cod = tnCod > 0` (`:8613-8615`).
|
||||
|
||||
`actualizeaza_vanzari` (`PACK_FACTURARE.pck:16015-16025`):
|
||||
|
||||
```
|
||||
16018 -- de modificat in caz ca il las sa stearga manual inregistrari din VANZARI_DETALII
|
||||
16019 -- acum se marcheaza cu STERS = 1 doar cand se sterge toata factura
|
||||
16020 UPDATE VANZARI_DETALII
|
||||
16021 SET STERS = 0
|
||||
16022 WHERE ID_VANZARE IN
|
||||
16023 (SELECT ID_VANZARE FROM VANZARI WHERE COD = V_COD_VECHI);
|
||||
16024 UPDATE VANZARI SET COD = V_COD_NOU, STERS = 0 WHERE COD = V_COD_VECHI;
|
||||
```
|
||||
|
||||
### De ce exista `STERS = 0` acolo (nu e cod mort)
|
||||
|
||||
E perechea lui `sterge_din_vanzari` -> `sterge_factura`, care marcheaza documentul sters:
|
||||
|
||||
```
|
||||
5549 UPDATE VANZARI_DETALII
|
||||
5550 SET STERS = V_STERS, ID_UTILS = V_ID_UTIL, DATAORAS = V_DATAORA
|
||||
5551 WHERE ID_VANZARE = V_ID_VANZARE
|
||||
5552 AND STERS = V_NESTERS
|
||||
```
|
||||
|
||||
Reeditarea unei note sterse trebuie sa readuca la viata si randul din `VANZARI`, si liniile lui.
|
||||
**Scoaterea reset-ului ar rupe fluxul „stergi nota, apoi o reeditezi" pe toata suita ROA.**
|
||||
|
||||
### Consecinta pentru S5 — mai grava decat „stergerile se pierd"
|
||||
|
||||
Reset-ul e **in bloc, fara nicio garda**: nici `AND STERS = 1` (irelevant), nici o discriminare
|
||||
intre „stersa ca linie" si „stersa odata cu documentul". `sterge_factura` marcheaza doar liniile
|
||||
active (`AND STERS = V_NESTERS`, `:5552`), deci o linie stearsa la o editare anterioara ramane
|
||||
`STERS=1` — si e **inviata** de `actualizeaza_vanzari` la urmatoarea salvare a notei.
|
||||
|
||||
Deci daca liniile se scriu inainte de `finalizeaza_modificare_nota`:
|
||||
|
||||
- stergerile din editarea CURENTA se pierd tacut;
|
||||
- **si**, independent de ce face utilizatorul acum, orice stergere facuta la o editare
|
||||
ANTERIOARA e anulata la fiecare salvare ulterioara — inclusiv la o salvare care nu atinge deloc
|
||||
articolele. Stergerea de linie **nu s-ar fixa niciodata**.
|
||||
|
||||
`UPDATE`-urile de pret/cantitate si `INSERT`-urile de linii noi ar supravietui — deci esecul e
|
||||
partial si asimetric, exact tipul care trece de un test superficial.
|
||||
|
||||
### Variantele de ordonare
|
||||
|
||||
**(a) VFP scrie detaliile inainte, `actualizeaza_vanzari` neatinsa.**
|
||||
Respinsa. Motivul complet e cel de mai sus: nu doar ca stergerile din sesiunea curenta se pierd,
|
||||
dar mecanismul de stergere de linie devine structural imposibil, fiindca fiecare salvare a notei
|
||||
reseteaza tot documentul la `STERS = 0`. In plus, dupa `actualizeaza_vanzari` `VANZARI.COD` s-a
|
||||
schimbat, deci orice scriere ulterioara ancorata pe `cod` ar rata randul (`ID_VANZARE` ramane —
|
||||
vezi A.1 din raportul precedent, reconfirmat la `:16024`).
|
||||
|
||||
**(a') VFP scrie inainte + `actualizeaza_vanzari` primeste o garda.**
|
||||
Respinsa. Ar cere un discriminator „stearsa ca linie" vs „stearsa cu documentul", care nu exista in
|
||||
schema (`VANZARI_DETALII` nu are alt marcaj decat `STERS`/`ID_UTILS`/`DATAORAS`); orice euristica
|
||||
pe `DATAORAS` e fragila. Si e Varianta A din raportul precedent — modificare in-place a unei
|
||||
proceduri apelate de **orice** editare de nota cu `cod` in `vanzari`, din toata suita ROA.
|
||||
|
||||
**(b) VFP scrie detaliile DUPA ce `finalizeaza_modificare_nota` s-a intors, apoi apeleaza
|
||||
`pack_facturare.recalculeaza_totaluri_vanzari(id_vanzare, discount)`, in aceeasi tranzactie.**
|
||||
**RECOMANDATA.** Verificat, nu presupus:
|
||||
|
||||
- **tranzactia e inca deschisa** cand se intoarce `finalizeaza_modificare_nota`: aceasta ruleaza la
|
||||
`ofacturare_comun.vc2:3826`, iar `do_inchide_tranzactie` abia la `:3828`; tranzactia e manuala pe
|
||||
`gnHandle` (`_frm_base.vc2:255`), aceeasi conexiune ODBC pe care ruleaza `goExecutor`. Deci
|
||||
scrierile de dupa intra in acelasi `COMMIT`/`ROLLBACK`, fara fereastra de inconsistenta.
|
||||
- `actualizeaza_vanzari` ramane **neatinsa** — zero regresie pe ROAGEST/ROACONT.
|
||||
- `PACK_CONTAFIN` ramane **neatins** — nu se recompileaza pachetul central de scriere a
|
||||
documentelor.
|
||||
- reset-ul `STERS = 0` ruleaza primul, iar VFP re-aplica dupa el starea autoritativa a liniilor.
|
||||
- `VANZARI.COD` e deja rescris cand VFP scrie — de aceea toate scrierile se ancoreaza pe
|
||||
`ID_VANZARE` (`lnIdVanzare`, citit din `crsfacturi` la `ofacturare_comun.vc2:3735`, stabil).
|
||||
|
||||
**Atentie — (b) naiv are un defect.** `IncarcaArticoleFactura` incarca **doar `sters = 0`**
|
||||
(`ofacturare_editare.prg:302`), deci liniile sterse la o editare anterioara nu sunt in
|
||||
`crsArticoleFactura`: reset-ul le-a inviat, iar VFP nu le atinge, deci raman active. Corectia e in
|
||||
**forma scrierii**, nu in Oracle — VFP scrie o stare completa, nu un delta:
|
||||
|
||||
```
|
||||
1. UPDATE VANZARI_DETALII SET STERS = 1, ID_UTILS = ?, DATAORAS = SYSDATE
|
||||
WHERE ID_VANZARE = <id> AND STERS = 0 -- marcheaza tot
|
||||
2. pentru fiecare linie pastrata din cursor, cu id_vanzare_det > 0:
|
||||
UPDATE VANZARI_DETALII SET STERS = 0, CANTITATE = ?, PRET = ?, PRET_CU_TVA = ?, ...
|
||||
WHERE ID_VANZARE_DET = <det> -- invie doar ce ramane
|
||||
3. pentru fiecare linie noua: INSERT INTO VANZARI_DETALII (...) -- ID_VANZARE_DET din trigger
|
||||
4. pack_facturare.recalculeaza_totaluri_vanzari(<id>, <discount>)
|
||||
```
|
||||
|
||||
Idiomul „marcheaza tot, invie ce ramane" e idempotent, nu are limita de 1000 de elemente intr-un
|
||||
`IN`, nu cere lista separata de linii sterse, si pastreaza sterse liniile scoase la editari
|
||||
anterioare. La pasul 2, `PRET_ACHIZITIE` se **omite** din `SET` (nu e in cursor — vezi 3).
|
||||
|
||||
**(c) recalcul apelat din interiorul `finalizeaza_modificare_nota`** (recomandarea raportului
|
||||
precedent, sectiunea B). **De abandonat.** Este incompatibila cu (b): daca recalculul ruleaza
|
||||
inauntrul lui `finalizeaza_modificare_nota`, el vede liniile **vechi** (VFP nu le-a scris inca,
|
||||
pentru ca nu poate scrie inainte de reset), deci ar produce exact totalurile de dinainte de editare
|
||||
— tacut corecte ca formula, tacut gresite ca valoare. Nu e o varianta mai riscanta, e o varianta
|
||||
gresita.
|
||||
|
||||
**(c') procedura Oracle care primeste si liniile** (prin `VANZARI_DETALII_TEMP` sau o colectie) si
|
||||
face si scrierea, si recalculul. Respinsa: reintroduce calea TEMP pe care planul a exclus-o explicit
|
||||
(`plan_06_editare_factura.md:106-114`), cere o forma de parametru incomoda prin ODBC, si dubleaza
|
||||
scrierea per-linie pe care planul a decis-o deja in VFP, dupa modelul `modifica_explicatie_articol`
|
||||
(`PACK_FACTURARE.pck:14514-14522`).
|
||||
|
||||
### Recomandare
|
||||
|
||||
**Varianta (b), cu scrierea in forma „marcheaza tot, invie ce ramane".** Argumentul decisiv nu e
|
||||
comoditatea, ci ca e **singura ordine in care reset-ul `STERS = 0` din `actualizeaza_vanzari` ramane
|
||||
inofensiv fara sa modificam procedura** — iar procedura aceea e folosita azi de toata suita, pentru
|
||||
un scop legitim (reeditarea unei note sterse) pe care nu-l putem sacrifica.
|
||||
|
||||
---
|
||||
|
||||
## 5. Discountul de document (`VANZARI.DISCOUNT`)
|
||||
|
||||
**Cine il scrie azi: nimeni, dupa emitere.** Verificat pe toata schema, nu doar pe `PACK_FACTURARE`:
|
||||
|
||||
- `all_source` (`PACKAGE BODY`/`PROCEDURE`/`FUNCTION`/`TRIGGER`, `MARIUSM_AUTO`), cautand
|
||||
`discount\s*=` exclusiv coloanele `discount_unitar|discount_tva|discount_evidentiat`: **niciun
|
||||
`UPDATE ... SET DISCOUNT = ...` pe `VANZARI`.** Rezultatele sunt toate pe alte tabele
|
||||
(`PACK_COMENZI.PROC_DISCOUNT`, `PACK_CRM.val_discount`, `PACK_OFERTARE.valdiscount`, ...).
|
||||
- Toate cele 8 instructiuni `UPDATE VANZARI` din `PACK_FACTURARE` (`:5485, :5493, :5516, :5615,
|
||||
:14817, :15387, :15397, :15509`) plus `modifica_date_factura` (`:14463-14512`, singura procedura
|
||||
de „modifica antetul facturii" existenta) ating `STERS`/`FACTURAT`/`ID_FACT`/`AVIZE`/
|
||||
`SERIE_ACT`/`NUMAR_ACT`/`DATA_ACT`/`DATA_SCAD` — **niciuna `DISCOUNT`**.
|
||||
- In VFP: cautare pe `COMUN\` dupa `set discount =` / `vanzari set ... discount` — **niciun
|
||||
rezultat**.
|
||||
- Trigger-ele pe `VANZARI` nu-l ating: `TRG_VANZARI_BEFOUPD` face doar audit pe
|
||||
`NR_ACT`/`SERIE_ACT`/`DATA_ACT`/`DATA_SCAD` (`pack_audit.verifica_val`).
|
||||
|
||||
Deci `VANZARI.DISCOUNT` e scris **o singura data in viata documentului**, la `INSERT`-ul din
|
||||
`scrie_in_vanzari` (`:13621` in lista de coloane, `:13682` in `VALUES`, din `V_DISCOUNT_FACTURA`).
|
||||
Nu exista nici procedura de modificare, nici cale VFP.
|
||||
|
||||
Pe partea VFP valoarea e deja disponibila in memorie: cursorul `tvanz` are coloana `discount`
|
||||
(`ofacturare_editare.prg:152`, `CreeazaCursorTvanzGol`), populata din `VANZARI` de
|
||||
`IncarcaVanzareNota` (`:176`).
|
||||
|
||||
### Recomandare: **parametru al procedurii noi**, nu `UPDATE` separat din VFP
|
||||
|
||||
```
|
||||
recalculeaza_totaluri_vanzari(V_ID_VANZARE IN NUMBER, V_DISCOUNT IN NUMBER DEFAULT NULL)
|
||||
```
|
||||
|
||||
cu semantica `V_DISCOUNT IS NULL` = „pastreaza valoarea curenta". Motive:
|
||||
|
||||
1. **discountul si totalurile nu pot diverge.** Cu doua instructiuni separate din VFP, un esec pe
|
||||
a doua (sau o omisiune la un viitor call-site) lasa `DISCOUNT` nou si totaluri calculate pe cel
|
||||
vechi. Cu un parametru, e imposibil sa recalculezi cu un discount invechit.
|
||||
2. procedura ramane utilizabila ca **recalcul pur** (fara al doilea argument) de oriunde altundeva
|
||||
— de exemplu dintr-un script de backfill.
|
||||
3. e o instructiune ODBC in minus pe drumul critic.
|
||||
|
||||
Implementare: `V_DISCOUNT` se aplica in acelasi `UPDATE vanzari` final,
|
||||
`discount = NVL(V_DISCOUNT, discount)`, iar valoarea folosita in agregare se citeste **inainte**,
|
||||
ca `NVL(V_DISCOUNT, (select discount from vanzari where id_vanzare = V_ID_VANZARE))` — altfel
|
||||
agregarea ar lucra pe discountul vechi.
|
||||
|
||||
---
|
||||
|
||||
## 6. Coloanele care NU se recalculeaza — reconfirmat pe sursa proaspata
|
||||
|
||||
`SERIE_INCASAT` / `NR_INCASAT` / `SUMA_INCASAT` / `TIP_INCASAT` (`:13777-13780`, scrise la
|
||||
`:13945-13948`) vin din `pack_facturare.cserie_act_incasare` / `nnumar_act_incasare` /
|
||||
`nsuma_incasare` / `ntip_doc_incasare`.
|
||||
|
||||
Cautare exhaustiva a atribuirilor catre aceste 4 variabile in `PACK_FACTURARE.pck` — **7 rezultate,
|
||||
toate in fluxul de emitere**:
|
||||
|
||||
```
|
||||
1882-1886 cserie_act_incasare := NULL; nnumar_act_incasare := NULL;
|
||||
ntip_doc_incasare := NULL; nsuma_incasare := NULL; (initializeaza_date_factura)
|
||||
13102-13105 cserie_act_incasare := V_SERIE_ACT_INCASARE; nnumar_act_incasare := V_NUMAR_ACT_INCASARE;
|
||||
ntip_doc_incasare := nTipIncasareChitanta; nsuma_incasare := 0;
|
||||
13136 nsuma_incasare := nsuma_incasare + ...
|
||||
13140,13144 ntip_doc_incasare := V_TIP / nTipIncasareBonFiscal;
|
||||
```
|
||||
|
||||
Sursele lor (`V_SERIE_ACT_INCASARE`, `V_NUMAR_ACT_INCASARE`) sunt parametri ai emiterii unei
|
||||
facturi-cu-incasare combinata. **Nu exista nicio tabela din care sa fie reconstituite la o editare
|
||||
ulterioara** — singura urma persistenta sunt chiar cele 4 coloane din `VANZARI`, care ar fi
|
||||
suprascrise cu `NULL` de o copiere naiva a `UPDATE`-ului.
|
||||
|
||||
**Concluzie reconfirmata: procedura noua scrie 11 coloane** (`discount_tva`, `valoare_achizitie`,
|
||||
`total_fara_tva`, `total_tva`, `total_cu_tva`, `valval`, `tvaval`, `totval`, `id_valuta`, `curs`,
|
||||
`multiplicator`), **plus optional `discount`** (vezi 5). Cele 4 de incasare raman la valoarea de la
|
||||
emitere.
|
||||
|
||||
---
|
||||
|
||||
## 7. Semnatura propusa si scripturile de migrare
|
||||
|
||||
### Declaratia din PACKAGE SPEC
|
||||
|
||||
Se adauga imediat dupa `actualizeaza_vanzari` (`PACK_FACTURARE.pck:1187-1188`), langa procedurile
|
||||
surori:
|
||||
|
||||
```sql
|
||||
PROCEDURE recalculeaza_totaluri_vanzari(V_ID_VANZARE IN NUMBER,
|
||||
V_DISCOUNT IN NUMBER DEFAULT NULL);
|
||||
```
|
||||
|
||||
`recalculeaza_totaluri_vanzari` = **29 de caractere**, sub limita de 30 a lui Oracle 10.2/11
|
||||
(peste 30 ar da `ORA-00972`). Nu mai lungi numele.
|
||||
|
||||
### Corpul (schita, compatibila 10.2)
|
||||
|
||||
Constructii folosite: `SELECT INTO`, `UPDATE`, `DECODE`, `CASE`, `NVL`, `ROUND`, `MAX`, `SUM`,
|
||||
`LEFT JOIN`, `UNION ALL`, `GROUP BY`, subinterogari inline. **Nimic din tabelul de incompatibilitati
|
||||
din `scripturi-migrare-db.md`** — fara `LISTAGG`, `CONTINUE`, `REGEXP_COUNT`, `FETCH FIRST`,
|
||||
`PIVOT`, `secventa.NEXTVAL` in atribuire.
|
||||
|
||||
```sql
|
||||
PROCEDURE recalculeaza_totaluri_vanzari(V_ID_VANZARE IN NUMBER,
|
||||
V_DISCOUNT IN NUMBER DEFAULT NULL) IS
|
||||
lnDiscountFactura VANZARI.DISCOUNT%TYPE;
|
||||
lnInValuta VANZARI.IN_VALUTA%TYPE;
|
||||
lnDiscountEvidentiat VANZARI.DISCOUNT_EVIDENTIAT%TYPE;
|
||||
lnDiscountTVA VANZARI.DISCOUNT_TVA%TYPE;
|
||||
lnValoareAchizitie VANZARI.VALOARE_ACHIZITIE%TYPE;
|
||||
lnTotalFaraTVA VANZARI.TOTAL_FARA_TVA%TYPE;
|
||||
lnTotalTVA VANZARI.TOTAL_TVA%TYPE;
|
||||
lnTotalCuTVA VANZARI.TOTAL_CU_TVA%TYPE;
|
||||
lnValVal VANZARI.VALVAL%TYPE;
|
||||
lnTVAVal VANZARI.TVAVAL%TYPE;
|
||||
lnTotVal VANZARI.TOTVAL%TYPE;
|
||||
lnIdValuta VANZARI.ID_VALUTA%TYPE;
|
||||
lnCurs VANZARI.CURS%TYPE;
|
||||
lnMultiplicator VANZARI.MULTIPLICATOR%TYPE;
|
||||
lnPrecizieCalcul NUMBER(2) := pack_sesiune.getOptiuneFirma('PC');
|
||||
lnPreciziePretV NUMBER(2) := pack_sesiune.getOptiuneFirma('PPRETV');
|
||||
BEGIN
|
||||
SELECT NVL(V_DISCOUNT, discount), in_valuta, NVL(discount_evidentiat, 0)
|
||||
INTO lnDiscountFactura, lnInValuta, lnDiscountEvidentiat
|
||||
FROM vanzari
|
||||
WHERE id_vanzare = V_ID_VANZARE;
|
||||
|
||||
-- acelasi bloc de agregare ca in scrie_in_vanzari (:13764-13931), cu trei substitutii:
|
||||
-- VANZARI_DETALII_TEMP a -> VANZARI_DETALII a WHERE a.id_vanzare = V_ID_VANZARE AND a.sters = 0
|
||||
-- vanzari_detalii_temp c -> vanzari_detalii c WHERE c.id_vanzare = V_ID_VANZARE AND c.sters = 0
|
||||
-- pack_facturare.nin_valuta -> lnInValuta
|
||||
-- pack_facturare.ndiscount_evidentiat -> lnDiscountEvidentiat
|
||||
-- V_DISCOUNT_FACTURA -> lnDiscountFactura
|
||||
-- fara coloanele de incasare (serie/nr/suma/tip)
|
||||
SELECT ... INTO lnDiscountTVA, lnValoareAchizitie, lnTotalFaraTVA, lnTotalTVA,
|
||||
lnTotalCuTVA, lnValVal, lnTVAVal, lnTotVal,
|
||||
lnIdValuta, lnCurs, lnMultiplicator
|
||||
FROM ( ... );
|
||||
|
||||
UPDATE vanzari
|
||||
SET discount = lnDiscountFactura,
|
||||
discount_tva = lnDiscountTVA,
|
||||
valoare_achizitie = lnValoareAchizitie,
|
||||
total_fara_tva = lnTotalFaraTVA,
|
||||
total_tva = lnTotalTVA,
|
||||
total_cu_tva = lnTotalCuTVA,
|
||||
valval = lnValVal,
|
||||
tvaval = lnTVAVal,
|
||||
totval = lnTotVal,
|
||||
id_valuta = lnIdValuta,
|
||||
curs = lnCurs,
|
||||
multiplicator = lnMultiplicator
|
||||
WHERE id_vanzare = V_ID_VANZARE;
|
||||
END recalculeaza_totaluri_vanzari;
|
||||
```
|
||||
|
||||
Idempotenta: `SELECT` + `UPDATE ... WHERE id_vanzare = :id`, fara `INSERT` — rularea de doua ori pe
|
||||
acelasi id da acelasi rezultat.
|
||||
|
||||
**Fara handler `WHEN NO_DATA_FOUND THEN NULL`** pe modelul originalului: la editare, un `id_vanzare`
|
||||
inexistent e o eroare reala care trebuie sa opreasca tranzactia, nu sa fie inghitita. (Primul
|
||||
`SELECT INTO`, pe cheia primara, e singurul care poate ridica `NO_DATA_FOUND`.)
|
||||
|
||||
### Scripturile de migrare
|
||||
|
||||
Azi, 09.08.2026, in `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08` nu exista niciun script cu data de azi
|
||||
(ultimele sunt `..._2026_08_08_01` si `..._2026_08_08_02`), deci **`NN` porneste de la `01`**.
|
||||
`NN` e secventa unica pe zi, comuna tuturor prefixelor.
|
||||
|
||||
**Un singur script**, fiindca S5 atinge un singur pachet si nimic altceva:
|
||||
|
||||
```
|
||||
ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql
|
||||
```
|
||||
|
||||
- prefix `ff_` — pachetul sta pe schema fiecarei firme;
|
||||
- **un pachet sta singur in scriptul lui**: fara DDL de tabele si fara DML alaturi (nu e nevoie de
|
||||
niciunul — nu se adauga coloane si nu se curata date);
|
||||
- contine SPEC + BODY (SPEC-ul se schimba: declaratia noua), CRLF obligatoriu, antet de 4-5 randuri,
|
||||
fara `select` de raportare, si se incheie cu
|
||||
`exec pack_migrare.UpdateVersiune('ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql');` + `commit;`;
|
||||
- `versiune_db.txt` din radacina proiectului se muta pe `2026_08_09_01` (fara newline final).
|
||||
|
||||
**Nu e nevoie de un script separat pentru `VVANZARI_ARTICOLE`** pentru S5 asa cum e proiectat aici
|
||||
— dar vezi intrebarea 3 de mai jos, care ar cere unul (`NN = 02`, si atunci **inainte** de cel al
|
||||
pachetului daca pachetul l-ar folosi; aici nu-l foloseste, deci ordinea e libera).
|
||||
|
||||
---
|
||||
|
||||
## 8. Riscuri si intrebari deschise
|
||||
|
||||
**R1 — Componentele de set sunt editabile in grid dar nu influenteaza totalurile. (mediu)**
|
||||
`VVANZARI_ARTICOLE` nu expune `ID_VANZARE_SET`, deci S4 nu poate distinge componentele de liniile
|
||||
normale; recalculul ia insa pretul/cantitatea din `VANZARI_SETURI`, nu din componente. Utilizatorul
|
||||
modifica o componenta, apasa salvare, totalul nu se schimba. Tacut.
|
||||
*Recomandarea mea:* pentru #6, **adauga `ID_VANZARE_SET` in `VVANZARI_ARTICOLE`** (script separat,
|
||||
`ff_2026_08_09_02_COMUN_VVANZARI_ARTICOLE.sql`) si fa liniile cu `id_vanzare_set` nenul
|
||||
**needitabile in grid**, cu o eticheta („linie din set"). Editarea seturilor e o functionalitate
|
||||
proprie, nu o extindere gratuita a lui S4. Alternativa minimala, daca Marius nu vrea scriptul de
|
||||
view: blocheaza intreaga factura care contine seturi — dar asta contrazice decizia din
|
||||
`plan_06_editare_factura.md:183-186` („fara blocarea facturilor care le contin").
|
||||
|
||||
**R2 — Stergerea unei componente de set. (mic, dar urat)**
|
||||
Cu idiomul „marcheaza tot, invie ce ramane", stergerea in grid a unei componente lasa capul de set
|
||||
in `VANZARI_SETURI` si celelalte componente pe loc: totalul ramane neschimbat (vine din cap), dar
|
||||
`VALOARE_ACHIZITIE` scade (se pierde `pret_achizitie`-ul componentei). Divergenta partiala.
|
||||
*Recomandare:* acoperit de R1 — daca liniile de set sunt needitabile, cazul dispare.
|
||||
|
||||
**R3 — `PRET_ACHIZITIE` NULL pe liniile noi anuleaza `VALOARE_ACHIZITIE` pe tot documentul. (mediu)**
|
||||
`SUM(round(cantitate * pret_achizitie))` cu un singur operand NULL nu da NULL pe total (SUM ignora
|
||||
NULL-urile), dar **linia noua nu contribuie deloc** — deci `VALOARE_ACHIZITIE` (baza de calcul a
|
||||
marjei) subestimeaza sistematic dupa fiecare adaugare de linie. Coloana nu e in cursorul din grid si
|
||||
nu are sursa la editare (la emitere vine din stoc/politica de pret).
|
||||
*Recomandare:* la `INSERT`-ul liniei noi, VFP scrie `PRET_ACHIZITIE` cu pretul de achizitie curent
|
||||
al articolului (acelasi lookup pe care il face `adauga_articol_factura_stoc`), sau, daca nu se poate
|
||||
determina, cu `0` explicit si o avertizare in verificarile din S4b. **Nu lasa NULL tacut.**
|
||||
|
||||
**R4 — Factura fara nicio linie da totaluri NULL, nu 0. (mic)**
|
||||
Agregatele pe zero randuri intorc NULL; la emitere cazul nu poate aparea, la editare da.
|
||||
*Recomandare:* nu modifica formula (ar diverge de original). Interzice in S4b salvarea unei facturi
|
||||
cu zero linii active — e oricum un document invalid.
|
||||
|
||||
**R5 — Linie cu valuta fara rand in `VANZARI_CURSURI`. (mic)**
|
||||
`left join vanzari_cursuri vc on vc.id_vanzare = V_ID_VANZARE and vd.id_valuta = vc.id_valuta`
|
||||
(`:13929-13930`): daca o linie ajunge cu o valuta pentru care documentul nu are curs, `vc.curs` e
|
||||
NULL si `pret_ron` iese NULL. `CreeazaPoArticolNouTvd` primeste explicit valuta documentului
|
||||
(`tnIdValutaDoc`, `ofacturare_editare.prg:356`), deci in fluxul proiectat nu ar trebui sa apara.
|
||||
**NEVERIFICAT** ca S4 chiar transmite acel parametru pe toate caile de adaugare.
|
||||
*Recomandare:* verificare in S4b, nu garda in Oracle.
|
||||
|
||||
**R6 — `pack_sesiune.getOptiuneFirma` intoarce `''` la orice eroare. (mic)**
|
||||
`PACK_SESIUNE` body `:128-131`: `WHEN OTHERS THEN lcValue := ''`. Atribuit intr-un `NUMBER(2)`, `''`
|
||||
devine NULL, iar `ROUND(x, NULL)` da NULL. Comportament identic cu cel de la emitere — deci nu e o
|
||||
regresie introdusa de S5, dar merita stiut daca apar totaluri NULL inexplicabile.
|
||||
*Recomandare:* nimic de facut in S5; consemnat pentru depanare.
|
||||
|
||||
**R7 — `ff_2026_08_08_01_COMUN_VVD_TOT.sql` aplicat in dev fara script pe disc. (de clarificat)**
|
||||
Obiectul nu exista in `all_objects` sub niciun nume `VVD%`, deci probabil scriptul a creat altceva
|
||||
sau a fost anulat ulterior. Fisierul lipseste din `SCRIPTURI_CLAR` -> nu ajunge la clienti.
|
||||
*Recomandare:* intrebare pentru Marius, nu blocheaza S5.
|
||||
|
||||
### Intrebari pentru Marius
|
||||
|
||||
1. **Liniile de set (R1)** — le facem needitabile in grid, cu `ID_VANZARE_SET` adaugat in
|
||||
`VVANZARI_ARTICOLE` printr-un al doilea script? *Recomandarea mea: da.* Fara asta, editarea unei
|
||||
facturi cu seturi arata ca merge si nu merge.
|
||||
2. **Discountul de document** — parametru al procedurii (`V_DISCOUNT ... DEFAULT NULL`), sau
|
||||
`UPDATE VANZARI SET DISCOUNT` separat din VFP? *Recomandarea mea: parametru*, ca discountul si
|
||||
totalurile sa nu poata diverge (vezi 5).
|
||||
3. **`PRET_ACHIZITIE` pe linia noua (R3)** — se citeste din nomenclator/stoc la adaugare, sau se
|
||||
scrie `0` cu avertizare? *Recomandarea mea: citit din nomenclator*, cu `0` doar ca ultima
|
||||
rezerva, niciodata NULL.
|
||||
4. **`VALVAL`/`TVAVAL`/`TOTVAL`** — raman in recalcul? *Recomandarea mea: da* (cost zero, fac parte
|
||||
din acelasi `SELECT`; excluderea lor ar lasa facturile in valuta inconsistente). Confirmare
|
||||
ceruta si in raportul precedent, inca neconfirmata.
|
||||
5. **`ff_2026_08_08_01_COMUN_VVD_TOT.sql`** — script de lucru abandonat, sau lipseste din SVN?
|
||||
|
||||
---
|
||||
|
||||
## Ce a ramas neverificat
|
||||
|
||||
- **R5**: nu am verificat pe codul S4 in lucru ca `CreeazaPoArticolNouTvd` primeste efectiv valuta
|
||||
documentului pe toate caile de adaugare de linie.
|
||||
- Nu am rulat nimic in Oracle in afara de `SELECT`-uri de dictionar si de export — **niciun DDL,
|
||||
niciun DML, niciun test de executie a procedurii propuse.** Corpul propus la 7 e schita, nu cod
|
||||
compilat.
|
||||
- Numarul de documente cu seturi in `MARIUSM_AUTO` (4) e din date de test si **nu constituie
|
||||
dovada** pentru niciuna dintre afirmatiile de mai sus; toate concluziile sunt din cod.
|
||||
296
docs/cercetare/rec_s5_script_oracle.md
Normal file
296
docs/cercetare/rec_s5_script_oracle.md
Normal file
@@ -0,0 +1,296 @@
|
||||
# Verificare script Oracle S5 — PACK_FACTURARE.recalculeaza_totaluri_vanzari
|
||||
|
||||
Data: 09.08.2026. Livrabil: `docs/ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql` (823433 octeti,
|
||||
17231 randuri; 17010->17231 fata de `.pck`-ul sursa, +221 randuri de continut adaugat).
|
||||
|
||||
Construit programatic dintr-un script PowerShell (nu retastat): citeste `PACK_FACTURARE.pck`
|
||||
(export proaspat, scratchpad, 810960 octeti, 17011 randuri) ca octeti ASCII, insereaza declaratia
|
||||
noua in SPEC dupa `actualizeaza_vanzari` si corpul nou in BODY dupa `actualizeaza_vanzari`, adauga
|
||||
`CREATE OR REPLACE` pe cele doua linii de start (absente in exportul brut din `all_source`),
|
||||
antetul si coada, si scrie rezultatul CRLF. Fiecare punct de insertie e verificat printr-un
|
||||
assert pe textul exact al ancorei (throw daca nu se potriveste) — scriptul s-a oprit si a fost
|
||||
corectat de doua ori in timpul lucrului (vezi „Erori prinse" mai jos), rularea finala a trecut
|
||||
toate ancorele.
|
||||
|
||||
## Ce s-a facut
|
||||
|
||||
1. **PACKAGE SPEC** (`.pck:1187-1189`): dupa declaratia `actualizeaza_vanzari`, s-a inserat
|
||||
`PROCEDURE recalculeaza_totaluri_vanzari(V_ID_VANZARE IN NUMBER, V_DISCOUNT IN NUMBER DEFAULT
|
||||
NULL);` — text identic cu cel din brief.
|
||||
2. **PACKAGE BODY** (`.pck:16015-16025`, dupa `END actualizeaza_vanzari;`): s-a inserat procedura
|
||||
noua, corpul fiind blocul de agregare din `scrie_in_vanzari` (`.pck:13762-13954`) cu substitutiile
|
||||
cerute, plus SELECT-ul de discount/in_valuta/discount_evidentiat inainte, plus `discount` in
|
||||
UPDATE, fara handler de exceptie — toate exact ca in sectiunea 7 a specificatiei.
|
||||
3. Antet de 6 randuri (4 randuri text + 1 rand `--` gol + titlu), fara referinte la planuri/rapoarte.
|
||||
4. Coada: `exec pack_migrare.UpdateVersiune('ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql'); commit;`
|
||||
|
||||
## Verificari cerute, cu cifre
|
||||
|
||||
**CRLF** — octeti LF fara CR inainte in fisierul final: **0**.
|
||||
|
||||
**Nume sub 30 caractere** — `'recalculeaza_totaluri_vanzari'.Length` = **29**. Confirmat.
|
||||
|
||||
**Diff-ul blocului de agregare** — original (`.pck:13762-13954`, 193 randuri, citat integral in
|
||||
`rec_s5_proiectare_oracle.md` sectiunea 2) vs. blocul nou din procedura (extras din fisierul
|
||||
livrat). Generat cu `diff -u -b` (ignora *doar* diferentele de cantitate de spatiu — necesar
|
||||
pentru ca tot blocul a fost mutat cu un nivel de indentare mai putin, vezi nota de mai jos; `-b`
|
||||
nu ascunde nicio diferenta de continut). Diff-ul integral:
|
||||
|
||||
```diff
|
||||
--- orig_block.txt (PACK_FACTURARE.pck:13762-13954)
|
||||
+++ new_block.txt (recalculeaza_totaluri_vanzari, corpul agregarii)
|
||||
@@ -1,5 +1,4 @@
|
||||
- -- Completare totaluri in vanzari din vanzari_detalii pentru a usura selectiile din fact_vfacturi
|
||||
- begin
|
||||
+-- Completare totaluri in vanzari din vanzari_detalii pentru a usura selectiile din fact_vfacturi
|
||||
select DISC_TVA_VAL AS DISCOUNT_TVA,
|
||||
VALOARE_ACHIZITIE,
|
||||
a.suma_fara_tva_ron - a.disc_fara_tva_ron as TOTAL_FARA_TVA,
|
||||
@@ -12,11 +11,7 @@
|
||||
a.disc_tva_val as TOTVAL,
|
||||
id_valuta,
|
||||
curs,
|
||||
- multiplicator,
|
||||
- pack_facturare.cserie_act_incasare as SERIE_INCASAT,
|
||||
- pack_facturare.nnumar_act_incasare as NR_INCASAT,
|
||||
- pack_facturare.nsuma_incasare AS SUMA_INCASAT,
|
||||
- pack_facturare.ntip_doc_incasare as TIP_INCASAT
|
||||
+ multiplicator
|
||||
INTO lnDiscountTVA,
|
||||
lnValoareAchizitie,
|
||||
lnTotalFaraTVA,
|
||||
@@ -27,29 +22,25 @@
|
||||
lnTotVal,
|
||||
lnIdValuta,
|
||||
lnCurs,
|
||||
- lnMultiplicator,
|
||||
- lnSerieIncasat,
|
||||
- lnNrIncasat,
|
||||
- lnSumaIncasat,
|
||||
- lnTipIncasat
|
||||
- FROM (select MAX(decode(pack_facturare.nin_valuta,
|
||||
+ lnMultiplicator
|
||||
+ FROM (select MAX(decode(lnInValuta,
|
||||
1,
|
||||
- ROUND(a1.curs * NVL(V_DISCOUNT_FACTURA, 0) /
|
||||
+ ROUND(a1.curs * NVL(lnDiscountFactura, 0) /
|
||||
a1.multiplicator,
|
||||
lnPreciziePretV),
|
||||
- NVL(V_DISCOUNT_FACTURA, 0))) as DISC_FARA_TVA_RON,
|
||||
- NVL(V_DISCOUNT_FACTURA, 0) as DISC_FARA_TVA_VAL,
|
||||
- pack_facturare.nin_valuta AS IN_VALUTA,
|
||||
- MAX(ROUND(decode(pack_facturare.nin_valuta,
|
||||
+ NVL(lnDiscountFactura, 0))) as DISC_FARA_TVA_RON,
|
||||
+ NVL(lnDiscountFactura, 0) as DISC_FARA_TVA_VAL,
|
||||
+ lnInValuta AS IN_VALUTA,
|
||||
+ MAX(ROUND(decode(lnInValuta,
|
||||
1,
|
||||
ROUND(a1.curs *
|
||||
- NVL(V_DISCOUNT_FACTURA, 0) /
|
||||
+ NVL(lnDiscountFactura, 0) /
|
||||
a1.multiplicator,
|
||||
lnPreciziePretV),
|
||||
- NVL(V_DISCOUNT_FACTURA, 0)) *
|
||||
+ NVL(lnDiscountFactura, 0)) *
|
||||
(a1.proc_tvav - 1),
|
||||
lnPreciziePretV)) as DISC_TVA_RON,
|
||||
- MAX(ROUND(NVL(V_DISCOUNT_FACTURA, 0) *
|
||||
+ MAX(ROUND(NVL(lnDiscountFactura, 0) *
|
||||
(a1.proc_tvav - 1),
|
||||
lnPreciziePretV)) as DISC_TVA_VAL,
|
||||
sum(pack_facturare.calculeaza_total_fara_tva_fact(a1.pret_ron,
|
||||
@@ -57,7 +48,7 @@
|
||||
1,
|
||||
NVL(a1.discount_unitar_ron,
|
||||
0),
|
||||
- pack_facturare.ndiscount_evidentiat,
|
||||
+ lnDiscountEvidentiat,
|
||||
a1.cantitate,
|
||||
a1.pret_cu_tva,
|
||||
a1.proc_tvav)) AS SUMA_FARA_TVA_RON,
|
||||
@@ -66,7 +57,7 @@
|
||||
1,
|
||||
NVL(a1.discount_unitar_ron,
|
||||
0),
|
||||
- pack_facturare.ndiscount_evidentiat,
|
||||
+ lnDiscountEvidentiat,
|
||||
a1.cantitate,
|
||||
a1.pret_cu_tva,
|
||||
a1.proc_tvav)) as SUMA_TVA_RON,
|
||||
@@ -75,7 +66,7 @@
|
||||
1,
|
||||
NVL(a1.discount_unitar_val,
|
||||
0),
|
||||
- pack_facturare.ndiscount_evidentiat,
|
||||
+ lnDiscountEvidentiat,
|
||||
a1.cantitate,
|
||||
a1.pret_cu_tva,
|
||||
a1.proc_tvav)) AS SUMA_FARA_TVA_VAL,
|
||||
@@ -84,18 +75,18 @@
|
||||
1,
|
||||
NVL(a1.discount_unitar_val,
|
||||
0),
|
||||
- pack_facturare.ndiscount_evidentiat,
|
||||
+ lnDiscountEvidentiat,
|
||||
a1.cantitate,
|
||||
a1.pret_cu_tva,
|
||||
a1.proc_tvav)) as SUMA_TVA_VAL,
|
||||
sum(round(a1.cantitate * a1.pret_achizitie,
|
||||
lnPrecizieCalcul)) AS VALOARE_ACHIZITIE,
|
||||
- max(decode(pack_facturare.nin_valuta, 1, a1.id_valuta, 0)) as id_valuta,
|
||||
- max(decode(pack_facturare.nin_valuta, 1, a1.curs, 1)) as curs,
|
||||
- max(decode(pack_facturare.nin_valuta, 1, a1.multiplicator, 1)) as multiplicator
|
||||
+ max(decode(lnInValuta, 1, a1.id_valuta, 0)) as id_valuta,
|
||||
+ max(decode(lnInValuta, 1, a1.curs, 1)) as curs,
|
||||
+ max(decode(lnInValuta, 1, a1.multiplicator, 1)) as multiplicator
|
||||
from (select vd.id_vanzare_set,
|
||||
(case
|
||||
- when (pack_facturare.nin_valuta = 1 or
|
||||
+ when (lnInValuta = 1 or
|
||||
vd.id_valuta <>
|
||||
pack_def.GetIdMonedaNationala()) then
|
||||
ROUND(vc.curs * vd.pret / vc.multiplicator,
|
||||
@@ -108,7 +99,7 @@
|
||||
vd.cantitate,
|
||||
vd.diferenta,
|
||||
(case
|
||||
- when (pack_facturare.nin_valuta = 1 or
|
||||
+ when (lnInValuta = 1 or
|
||||
vd.id_valuta <>
|
||||
pack_def.GetIdMonedaNationala()) then
|
||||
ROUND(vc.curs * vd.discount_unitar /
|
||||
@@ -132,8 +123,10 @@
|
||||
a.id_valuta,
|
||||
a.pret_cu_tva,
|
||||
a.pret_achizitie
|
||||
- from VANZARI_DETALII_TEMP a
|
||||
+ from VANZARI_DETALII a
|
||||
where nvl(a.id_vanzare_set, 0) = 0
|
||||
+ and a.id_vanzare = V_ID_VANZARE
|
||||
+ and a.sters = 0
|
||||
union all
|
||||
select b.id_vanzare_set,
|
||||
b.pret,
|
||||
@@ -141,7 +134,7 @@
|
||||
b.cantitate,
|
||||
0 as diferenta,
|
||||
b.discount_unitar,
|
||||
- decode(pack_facturare.nin_valuta,
|
||||
+ decode(lnInValuta,
|
||||
0,
|
||||
pack_def.GetIdMonedaNationala(),
|
||||
c.id_valuta) as id_valuta,
|
||||
@@ -151,17 +144,19 @@
|
||||
0,
|
||||
c.pret_achizitie * c.cantitate /
|
||||
b.cantitate)) as pret_achizitie
|
||||
- from vanzari_detalii_temp c
|
||||
+ from vanzari_detalii c
|
||||
left join vanzari_seturi b
|
||||
on b.id_vanzare_set = c.id_vanzare_set
|
||||
where nvl(c.id_vanzare_set, 0) <> 0
|
||||
- and nvl(pack_facturare.nin_valuta, -1) > -1
|
||||
+ and c.id_vanzare = V_ID_VANZARE
|
||||
+ and c.sters = 0
|
||||
+ and nvl(lnInValuta, -1) > -1
|
||||
group by b.id_vanzare_set,
|
||||
b.pret,
|
||||
b.cantitate,
|
||||
b.discount_unitar,
|
||||
b.pret_cu_tva,
|
||||
- decode(pack_facturare.nin_valuta,
|
||||
+ decode(lnInValuta,
|
||||
0,
|
||||
pack_def.GetIdMonedaNationala(),
|
||||
c.id_valuta)) vd
|
||||
@@ -170,7 +165,8 @@
|
||||
and vd.id_valuta = vc.id_valuta) a1) a;
|
||||
|
||||
update vanzari
|
||||
- set discount_tva = lnDiscountTVA,
|
||||
+ set discount = lnDiscountFactura,
|
||||
+ discount_tva = lnDiscountTVA,
|
||||
valoare_achizitie = lnValoareAchizitie,
|
||||
total_fara_tva = lnTotalFaraTVA,
|
||||
total_tva = lnTotalTVA,
|
||||
@@ -180,14 +176,5 @@
|
||||
totval = lnTotVal,
|
||||
id_valuta = lnIdValuta,
|
||||
curs = lnCurs,
|
||||
- multiplicator = lnMultiplicator,
|
||||
- serie_incasat = lnSerieIncasat,
|
||||
- nr_incasat = lnNrIncasat,
|
||||
- suma_incasat = lnSumaIncasat,
|
||||
- tip_incasat = lnTipIncasat
|
||||
+ multiplicator = lnMultiplicator
|
||||
where id_vanzare = V_ID_VANZARE;
|
||||
-
|
||||
- exception
|
||||
- when NO_DATA_FOUND then
|
||||
- null;
|
||||
- end;
|
||||
```
|
||||
|
||||
Diff-ul contine **exact**: cele 6 substitutii din tabelul din brief (`nin_valuta`->`lnInValuta` x11,
|
||||
`ndiscount_evidentiat`->`lnDiscountEvidentiat` x4, `NVL(V_DISCOUNT_FACTURA, 0)`->
|
||||
`NVL(lnDiscountFactura, 0)` x6, cele doua perechi FROM/WHERE), eliminarea celor 4 coloane de
|
||||
incasare din SELECT/INTO/UPDATE (cu fixarea virgulei ramase), adaugarea `discount =
|
||||
lnDiscountFactura,` in UPDATE si eliminarea wrapper-ului `begin ... exception ... end;` (cerut
|
||||
explicit: „Fara handler WHEN NO_DATA_FOUND THEN NULL"). **Nicio alta diferenta de continut.**
|
||||
|
||||
Nota pe metoda: `-b` a fost necesar (nu `diff` simplu) pentru ca tot blocul, o data scos din
|
||||
`begin...end;`-ul intern, a coborat cu un nivel de indentare (2 spatii) — o consecinta mecanica,
|
||||
uniforma, a aplatizarii cerute de sectiunea 7, nu o modificare de continut. Fara `-b`, diff-ul ar
|
||||
fi aratat *toate* liniile ca schimbate, desi doar spatiul de inceput difera pe liniile
|
||||
neatinse de tabelul de substitutii (verificat separat: liniile fara nicio substitutie, ex.
|
||||
`select DISC_TVA_VAL AS DISCOUNT_TVA,`, `VALOARE_ACHIZITIE,`, nu apar deloc in diff-ul de mai sus).
|
||||
|
||||
**`;` in comentarii `--` in interiorul unei instructiuni** — 11 aparitii ale tiparului `--.*;` in
|
||||
tot fisierul, **toate preexistente** in codul neatins (`scrie_incasari`, `contabilizeaza_articol`
|
||||
etc., linii 5908-14852 din script), **niciuna** introdusa de mine (verificat separat: 0 in antetul
|
||||
nou, 0 in declaratia SPEC noua, 0 in corpul noii proceduri). Riscul descris in
|
||||
`scripturi-migrare-db.md` (SP2-0734) se aplica instructiunilor SQL terminate cu `;`
|
||||
(`CREATE VIEW` etc.); intregul script de fata e un singur bloc `CREATE OR REPLACE PACKAGE`/
|
||||
`PACKAGE BODY` terminat cu `/`, deci riscul nu se aplica structural — dar cifra e cea ceruta.
|
||||
|
||||
**Constructii peste Oracle 10.2** — scanat corpul noii proceduri pentru
|
||||
`LISTAGG|CONTINUE|REGEXP_COUNT|FETCH FIRST|PIVOT|NEXTVAL`: **0 aparitii** pentru fiecare.
|
||||
Identificatori: cel mai lung e `recalculeaza_totaluri_vanzari` (29) si `lnDiscountEvidentiat` (20)
|
||||
— niciunul peste 30.
|
||||
|
||||
**Numarul de linii** — fisier final: **17231** (17230 dupa convenția `wc -l`, care nu numara
|
||||
ultimul rand fiindca fisierul, la fel ca sursa, nu are newline final); `.pck` original:
|
||||
**17011** (17010 `wc -l`). Delta: +221 randuri adaugate (antet 7 + insert SPEC 3 + rand gol inainte
|
||||
de `CREATE OR REPLACE PACKAGE BODY` 1 + procedura noua in BODY 205 + coada 4 + `CREATE OR REPLACE`
|
||||
adaugat pe 2 linii existente, fara linii noi acolo).
|
||||
|
||||
**Coloanele de incasare** — `serie_incasat`, `nr_incasat`, `suma_incasat`, `tip_incasat`: **0**
|
||||
aparitii in SELECT/INTO/UPDATE-ul noii proceduri (verificat separat, izolat pe textul extras al
|
||||
procedurii). Apar in continuare de 5 ori fiecare **in restul fisierului** — in `scrie_in_vanzari`,
|
||||
neatinsa, unde e corect sa ramana (comportamentul de emitere nu se schimba).
|
||||
|
||||
## Erori prinse si corectate in timpul lucrului (nu au ajuns in fisierul livrat)
|
||||
|
||||
1. Prima rulare a omis complet linia `discount = lnDiscountFactura,` din `UPDATE` (am copiat doar
|
||||
eliminarea coloanelor de incasare, am uitat adaugarea cerincetei separat in brief). Prins de
|
||||
verificarea numerica (`lnDiscountFactura` aparea de 8 ori in loc de 9) inainte de a scrie
|
||||
raportul; corectat si re-rulat.
|
||||
2. Prima rulare a scris `PACKAGE "PACK_FACTURARE" is` si `PACKAGE BODY PACK_FACTURARE is` fara
|
||||
prefixul `CREATE OR REPLACE` pe **linia de SPEC** (l-am adaugat doar pe linia de BODY). Ar fi
|
||||
dat eroare de sintaxa la aplicare — `PACKAGE ... is` singur nu e o instructiune DDL valida.
|
||||
Prins prin citirea directa a antetului fisierului scris; corectat si re-rulat.
|
||||
|
||||
## Ce NU am facut / neverificat
|
||||
|
||||
- Nu am rulat nimic in Oracle — niciun `sqlplus`, niciun DDL, niciun test de compilare a
|
||||
pachetului. Corectitudinea sintactica dincolo de verificarile de mai sus (paranteze, virgule,
|
||||
cuvinte cheie) nu e garantata decat prin inspectie si prin construirea mecanica din blocul
|
||||
original deja compilat.
|
||||
- Coada scriptului foloseste `UpdateVersiune('ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql')` **cu**
|
||||
extensia `.sql`, asa cum cere explicit brief-ul si `scripturi-migrare-db.md` („script_final =
|
||||
numele fisierului, cu tot cu .sql"). Modelul citat (`ff_2026_08_06_10_...sql:17019`) foloseste
|
||||
de fapt numele **fara** `.sql` — o inconsistenta intre precedent si regula scrisa. Am urmat
|
||||
regula scrisa si instructiunea explicita, nu precedentul; semnalez discrepanta, nu am
|
||||
„reparat-o" in modelul vechi (nu era in scop).
|
||||
- Nu am atins `versiune_db.txt`, nu am scris in `D:\ROA\DATABASE\SCRIPTURI_CLAR`, nu am dat
|
||||
commit — conform interdictiilor din brief.
|
||||
341
docs/cercetare/rec_tva_vanzari.md
Normal file
341
docs/cercetare/rec_tva_vanzari.md
Normal file
@@ -0,0 +1,341 @@
|
||||
# Cercetare: TVA calculat vs salvat (#7) + denormalizare VANZARI (#8)
|
||||
|
||||
Sursele principale sunt fisierele "curate" din arhiva de migrare Oracle
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\...` (nu in working copy VFP git — DDL/PL-SQL nu e versionat in
|
||||
`ROAFACTURARE`), plus `D:\ROA\ROAFACTURARE\COMUN\clase\ofacturare.vc2` (working copy VFP, text
|
||||
`.vc2` deja la zi).
|
||||
|
||||
Cea mai recenta definitie **completa** a pachetului `PACK_FACTURARE` (COMUN, folosit de toate
|
||||
produsele ROA care factureaza) e in
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql` (16948 linii).
|
||||
Toate liniile citate mai jos fara alta mentiune sunt din acest fisier.
|
||||
|
||||
---
|
||||
|
||||
## SUBIECT A — TVA calculat, nu salvat (#7)
|
||||
|
||||
### 1. Structura VANZARI / VANZARI_DETALII (coloane pret/TVA)
|
||||
|
||||
Nu exista `CREATE TABLE VANZARI_DETALII` in arhiva cautata (tabela e mai veche decat
|
||||
`SCRIPTURI_CLAR`, care incepe efectiv din 2009; originea e probabil in
|
||||
`D:\ROA\DATABASE\SCRIPTURI\2006-2008`, nu am parcurs exhaustiv acel arhiv de migrari vechi).
|
||||
Coloanele efective au fost confirmate prin utilizarea lor in cod (view-uri + SQL dinamic VFP):
|
||||
|
||||
**VANZARI_DETALII** (per linie articol):
|
||||
- `PRET` — pret unitar (fara/cu TVA, in functie de flag)
|
||||
- `DIFERENTA` — ajustare pret (folosita in `calculeaza_total_*_fact`)
|
||||
- `DISCOUNT_UNITAR`
|
||||
- `CANTITATE`
|
||||
- `PRET_CU_TVA` — flag NUMBER(1): 1 = pretul de mai sus e cu TVA inclus, 0 = fara TVA
|
||||
(`ff_2026_07_27_01_FACTURARE.sql:25,43` — `b.pret_cu_tva`)
|
||||
- `PROC_TVAV` — procent TVA ca multiplicator (ex. 1.19), nu procent brut
|
||||
(`ff_2026_07_27_01_FACTURARE.sql:26` — `b.proc_tvav`)
|
||||
- `PRET_ACHIZITIE` (`ff_2026_07_27_01_FACTURARE.sql:105,130`)
|
||||
- `ID_ARTICOL`, `ID_VALUTA`, `ID_POL` (politica de pret), `SERIE`, `STERS`, `ID_VANZARE`,
|
||||
`ID_VANZARE_DET` (`ff_2026_07_27_01_FACTURARE.sql:11-76`)
|
||||
- `TAXCODE` — adaugata `2022\03\ff_2022_03_24_01_COMUN_SAFT.sql:6` (cod taxa SAFT)
|
||||
- `ID_JTVA_COLOANA_EX` — adaugata `2019\08\ff_2019_08_20_04_COMUN.sql:7`
|
||||
- `LOT` — adaugata `2024\06\ff_2024_06_04_01_COMUN_FACTURARE.sql:3`
|
||||
|
||||
**NU exista** o coloana de TVA calculata/salvata per linie (nici `valoare_tva`, nici
|
||||
`pret_fara_tva` rezultat) — doar inputurile (`pret`, `pret_cu_tva` flag, `proc_tvav`), confirmand
|
||||
exact ce zice todo #7: TVA e derivat, nu stocat.
|
||||
|
||||
**VANZARI** (antet factura) — coloane denormalizate relevante TVA, toate adaugate prin
|
||||
`2017\03\ff_2017_03_28_01_FACTURARE.sql:9-38`:
|
||||
- `DISCOUNT_TVA` — "TVA DISCOUNT (DISCOUNT * MAX(PROC_TVA) ARTICOLE)"
|
||||
- `TOTAL_FARA_TVA`, `TOTAL_TVA`, `TOTAL_CU_TVA` — totaluri pe document (denormalizate)
|
||||
- `VALOARE_ACHIZITIE`
|
||||
- vezi si Subiect B pt. `SERIE_INCASAT`/`NR_INCASAT`/`SUMA_INCASAT`/`TIP_INCASAT`/`AVIZE`
|
||||
|
||||
### 2. Unde se calculeaza TVA-ul pe linie — toate locurile
|
||||
|
||||
Calculul e centralizat in doua straturi Oracle, apelate de fiecare punct de consum (VFP nu face
|
||||
calcul TVA local — doar construieste SQL dinamic care cheama functiile Oracle):
|
||||
|
||||
- **`PACK_SESIUNE.calculeaza_pret_fara_tva/tva/cu_tva`** — motorul de rotunjire per-unitate de
|
||||
pret (nu e in `PACK_FACTURARE`; pachetul `PACK_SESIUNE` nu a fost gasit definit separat in
|
||||
arhiva cautata — cautare punctuala pe cateva luni din 2025/2026, fara succes; probabil e intr-un
|
||||
script `COMUN_PACK_SESIUNE` mai vechi, netestat exhaustiv).
|
||||
- **`PACK_FACTURARE.calculeaza_pret`** (linia 14557) — wrapper subtire peste cele 3 functii
|
||||
`PACK_SESIUNE` de mai sus.
|
||||
- **`PACK_FACTURARE.calculeaza_sume`** (linia 14631, spec 980) — calculeaza suma_fara_tva /
|
||||
suma_tva / suma_cu_tva pe linie (cantitate * pret), delegand catre:
|
||||
- **`calculeaza_total_fara_tva`** (linia 15745/15769) — delega la `pack_sesiune.calculeaza_total_fara_tva`
|
||||
- **`calculeaza_total_tva`** (linia 15850/15874) — delega la `pack_sesiune.calculeaza_total_tva`
|
||||
- **`calculeaza_total_cu_tva`** (linia 15638/15662) — delega la `pack_sesiune.calculeaza_total_cu_tva`
|
||||
- variantele `_fact` (`calculeaza_total_fara_tva_fact` 15794, `calculeaza_total_tva_fact` 15899,
|
||||
`calculeaza_total_cu_tva_fact` 15687) au **formula proprie inline** (nu delega la
|
||||
`pack_sesiune`), documentata explicit in cod ca fiind "folosita in view-ul
|
||||
fact_vrap_centralizator_fact" (comentarii 15686, 15744, 15793, 15848, 15897).
|
||||
|
||||
Formula `_fact` (exemplu `calculeaza_total_tva_fact`, 15899-15949) e explicit ROUND-based, cu
|
||||
ramuri separate pentru `discount_evidentiat` — aici e punctul central de rotunjire per linie.
|
||||
|
||||
- **Puncte de CONSUM ale acestor functii** (unde efectiv se calculeaza TVA afisat/raportat):
|
||||
- Views `fact_vrap_fact_articole` si `fact_vrap_articole_vandute`
|
||||
(`ff_2026_07_27_01_FACTURARE.sql:18-44, 131-196` — apeleaza
|
||||
`calculeaza_total_fara_tva`/`calculeaza_total_tva` direct in `SELECT`)
|
||||
- Raport VFP dinamic: `COMUN\programe\oproceduri_rapoarte_fact.prg:581-590` — SQL construit in
|
||||
VFP apeleaza direct `pack_sesiune.calculeaza_pret_cu_tva(...)` si
|
||||
`pack_sesiune.calculeaza_total_cu_tva(...)` pentru listare/relistare rapoarte articole vandute.
|
||||
- `PACK_FACTURARE.scrie_in_vanzari` (13468) si `finalizeaza_avize_lucrare` (14807) — calculeaza
|
||||
si scriu `VANZARI.TOTAL_FARA_TVA`/`TOTAL_CU_TVA` folosind `calculeaza_total_fara_tva_fact` in
|
||||
subquery-uri (13716-13786, 14965-15008).
|
||||
- `verifica_total_document` (16009) — vezi punctul 5, verifica totalul calculat vs. cel din
|
||||
notele contabile si genereaza o corectie.
|
||||
|
||||
Nu am gasit un apel VFP direct catre `calculeaza_pret(` sau `calculeaza_sume(` in working copy
|
||||
`ROAFACTURARE`/`COMUN` (grep pe nume exact, fara rezultate) — deci formularul de introducere
|
||||
factura in VFP nu recalculeaza local pretul/TVA-ul linie cu linie prin apel explicit de
|
||||
procedura; cel mai probabil articolele + preturile lor (deja cu `pret`, `pret_cu_tva`,
|
||||
`proc_tvav`) vin dintr-un cursor Oracle (`PACK_FACTURARE.cursor_preturi`, spec 335, body 2121)
|
||||
populat cand se adauga articolul, iar TVA vizibila in grid e calculata la afisare din acele
|
||||
coloane brute — nu am gasit expresia VFP exacta (`cursor_preturi` e ~500 linii, nu am parcurs
|
||||
linie cu linie in bugetul acestei cercetari).
|
||||
|
||||
### 3. Ce inseamna "preturi_cu_tva" / `pret_cu_tva`
|
||||
|
||||
- Pe linie: `VANZARI_DETALII.PRET_CU_TVA` — NUMBER(1), 0/1, transmis ca parametru `V_PRET_CU_TVA`
|
||||
/ `V_PRET_ARE_TVA` la toate functiile de calcul de mai sus (controleaza care ramura de formula
|
||||
se aplica — pornind de la pret cu TVA sau fara TVA).
|
||||
- In grid-ul VFP exista o coloana **checkbox** `cPret_cu_tva` in
|
||||
`D:\ROA\ROAFACTURARE\Clase\ofundal_facturare.vc2:696-699` (`_grdrow2.cPret_cu_tva...`) — probabil
|
||||
afiseaza/permite editarea flagului per linie in formular.
|
||||
- **Nu am gasit** coloana `PRET_CU_TVA` (sau similara) direct pe `CRM_POLITICI_PRETURI` in
|
||||
scripturile de migrare cautate (am cautat `ALTER TABLE CRM_POLITICI_PRETURI ADD`, fara hit
|
||||
pe acest nume) — deci originea exacta a valorii implicite per politica de pret ("politica are
|
||||
bifat 'preturi fara TVA'", cum descrie todo #7) nu e confirmata cu `fisier:linie`; e probabil
|
||||
citita/propagata in `PACK_FACTURARE.cursor_preturi` (2121) sau
|
||||
`citeste_setari_pol_pret` (spec 324, body 2025) cand se adauga articolul pe factura — nu am
|
||||
parcurs acele corpuri in detaliu (buget de cercetare).
|
||||
|
||||
### 4. Locuri de atins daca s-ar salva `pret_cu_tva`/`valoare_tva` per linie real (nu calculat)
|
||||
|
||||
Enumerare pe baza punctelor de consum gasite mai sus:
|
||||
|
||||
1. **DDL**: `ALTER TABLE VANZARI_DETALII ADD (valoare_tva, pret_fara_tva_calculat, ...)` — coloane
|
||||
noi + migrare date istorice.
|
||||
2. **`PACK_FACTURARE`** (Oracle, `ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql`):
|
||||
- `adauga_articol_factura` (spec 529, body 4972) — punctul unde se insereaza linia in
|
||||
`VANZARI_DETALII_TEMP`; ar trebui sa scrie valoarea (eventual editata de user) in loc s-o
|
||||
lase doar pe `pret`/`pret_cu_tva`/`proc_tvav`.
|
||||
- `calculeaza_sume` (14631) — daca valoarea e editabila, aceasta procedura ar trebui sa
|
||||
citeasca valoarea salvata in loc s-o recalculeze, sau sa fie ocolita.
|
||||
- `scrie_in_vanzari` (13468) si `finalizeaza_avize_lucrare` (14807) — subquery-urile care insumeaza
|
||||
`calculeaza_total_fara_tva_fact`/`calculeaza_total_tva_fact` pe toate liniile
|
||||
(13716-13786, 14965-15008) ar trebui sa insumeze coloana noua in loc s-o recalculeze.
|
||||
- `verifica_total_document` (16009) — logica de reconciliere total-vs-note-contabile ar trebui
|
||||
ajustata (vezi punct 5) daca totalul nu se mai deriva strict din formula.
|
||||
3. **Views Oracle**: `fact_vrap_fact_articole`, `fact_vrap_articole_vandute`
|
||||
(`ff_2026_07_27_01_FACTURARE.sql:10-257`), `fact_vfacturi`/`fact_vfacturi2` (vezi Subiect B #11)
|
||||
— toate ar trebui sa citeasca noua coloana in loc de `calculeaza_total_*`.
|
||||
4. **VFP**: `COMUN\programe\oproceduri_rapoarte_fact.prg:581-590` — SQL-ul de raport care apeleaza
|
||||
direct `pack_sesiune.calculeaza_pret_cu_tva`/`calculeaza_total_cu_tva`.
|
||||
5. **VFP grid formular**: `D:\ROA\ROAFACTURARE\Clase\ofundal_facturare.vc2` (coloana
|
||||
`cPret_cu_tva` + coloanele de pret/valoare din grid — nu identificate exhaustiv, cautare
|
||||
punctuala doar pe flag).
|
||||
6. **Rapoarte `.frx`** care afiseaza TVA pe linie de factura (ex. `usr_factura*.fr2` — 25 de
|
||||
fisiere gasite cu referinta la `PACK_FACTURARE`, listate la cautarea initiala; nu au fost
|
||||
deschise individual).
|
||||
|
||||
Estimare: minim **6 zone distincte** (DDL, pachet Oracle ~4 proceduri, 3-4 views, 1 program raport
|
||||
VFP, grid formular, rapoarte `.frx`) — consistent cu observatia ca e o schimbare "de volum", nu
|
||||
locala.
|
||||
|
||||
### 5. Mecanism existent de ajustare/rotunjire
|
||||
|
||||
**Da, exista, dar la nivel contabil, nu la nivel de linie facturata / vizibil userului.**
|
||||
|
||||
`PACK_FACTURARE.verifica_total_document` (linia 16009-16188+) compara totalul FTVA/TVA asteptat
|
||||
(`pack_facturare.ntotftva`, populat din VFP la `pnTotalFtva`/`Thisform.nbazaron`) cu suma reala din
|
||||
notele contabile generate (`ACT_TEMP`, grupate pe conturi `4111`/`4427`/`418`/`4428`). Daca difera
|
||||
(16082-16083: `NVL(pack_facturare.ntotftva,0) <> V_TOTFTVA_VER`), calculeaza diferenta
|
||||
`pack_facturare.ndifftva := pack_facturare.ntotftva - V_TOTFTVA_VER` (16085) si **insereaza automat
|
||||
o linie de corectie in `ACT_TEMP`** (16086-16188, INSERT cu `suma => pack_facturare.ndifftva`) —
|
||||
adica ajustarea de rotunjire se absoarbe silentios in nota contabila, nu apare ca linie editabila
|
||||
pe factura si nu se reflecta in `VANZARI_DETALII`. Aceasta e probabil exact mecanismul care face ca
|
||||
utilizatorul sa nu poata corecta manual TVA-ul afisat: rotunjirea se "repara" doar in contabilitate,
|
||||
dupa fapt.
|
||||
|
||||
---
|
||||
|
||||
## SUBIECT B — Denormalizare VANZARI, bug facturi din avize + numerar (#8)
|
||||
|
||||
### 6. Locatia `PACK_FACTURARE`
|
||||
|
||||
Nu exista fisier `.pck`/`.sql` cu acest pachet in working copy `ROAFACTURARE` (nici in `COMUN/`
|
||||
local) — **e in afara working copy-ului VFP**, in arhiva DDL/PL-SQL Oracle
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\`. Cea mai recenta versiune completa (16948 linii):
|
||||
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql`
|
||||
|
||||
(exista si un diff mai nou, doar pe view-uri, `2026\07\ff_2026_07_27_01_FACTURARE.sql` — vezi #11).
|
||||
Istoricul complet de modificari e in `SCRIPTURI_CLAR\<an>\<luna>\ff_..._COMUN_PACK_FACTURARE.sql`
|
||||
respectiv `..._FACTURARE.sql` (zeci de fisiere, 2006-2026).
|
||||
|
||||
### 7. Procedura care scrie in VANZARI valorile denormalizate
|
||||
|
||||
**`PACK_FACTURARE.scrie_in_vanzari`** (spec linia 894, body **linia 13468-13908**) — apelata din
|
||||
`finalizeaza_factura` (linia **14740**). Face `UPDATE VANZARI SET ...` cu (13886-13898):
|
||||
|
||||
```
|
||||
total_fara_tva = lnTotalFaraTVA,
|
||||
...
|
||||
total_cu_tva = lnTotalCuTVA,
|
||||
...
|
||||
serie_incasat = lnSerieIncasat,
|
||||
nr_incasat = lnNrIncasat,
|
||||
suma_incasat = lnSumaIncasat,
|
||||
tip_incasat = lnTipIncasat
|
||||
```
|
||||
|
||||
unde `lnSerieIncasat`/`lnNrIncasat`/`lnSumaIncasat`/`lnTipIncasat` sunt populate (13727-13730) din
|
||||
variabilele **de pachet** `pack_facturare.cserie_act_incasare`, `.nnumar_act_incasare`,
|
||||
`.nsuma_incasare`, `.ntip_doc_incasare` (declarate 179-182).
|
||||
|
||||
O a doua ramura echivalenta exista in **`finalizeaza_avize_lucrare`** (spec 1011, body
|
||||
**14807-15176**), care face acelasi UPDATE (15124-15130) — pentru ramura "avize pe lucrare".
|
||||
|
||||
Variabilele de pachet `cserie_act_incasare`/`nnumar_act_incasare`/`ntip_doc_incasare`/
|
||||
`nsuma_incasare` sunt setate **doar** de **`PACK_FACTURARE.scrie_incasari`** (spec 864, body
|
||||
**13070-13139**), apelata condiționat (`IF V_LISTA_INCASARE IS NOT NULL`) din:
|
||||
- `scrie_factura2` — linia **6178** (ramura factura normala / comanda / contract)
|
||||
- `scrie_factura_avize` — linia **7008** (ramura **factura din aviz**)
|
||||
|
||||
Sunt resetate la `NULL` in `initializeaza_date_factura` (comentariu 1384-1386, cod la
|
||||
**1876-1880**) — fix explicit din 03.07.2020: *"ramaneau completate pe facturile urmatoare de la o
|
||||
factura anterioara"*.
|
||||
|
||||
`VANZARI.AVIZE` (seria/numarul avizelor facturate) e scris de
|
||||
**`scrie_corespondente_vanzari`** (spec 1057, body **15421-15457**, comentariu la linia **15445**:
|
||||
*"Completez VANZARI.AVIZE redundant, pentru a nu face mai rapid fact_vfacturi"*) — nu am confirmat
|
||||
in acest buget de cercetare din ce apeleaza `finalizeaza_factura` daca `scrie_corespondente_vanzari`
|
||||
ruleaza necondiționat pe toate tipurile sau doar pe unele (`V_TIP` e parametru) — merita verificat
|
||||
punctual daca se investigheaza bug-ul mai departe.
|
||||
|
||||
### 8. Coloanele denormalizate din VANZARI si ramura care le populeaza
|
||||
|
||||
Toate adaugate prin `2017\03\ff_2017_03_28_01_FACTURARE.sql:9-38` (comentariu fisier, linia 1-4:
|
||||
*"adaugare coloane in vanzari pentru denormalizarea join-urilor din fact_vfacturi"*):
|
||||
|
||||
| Coloana | Comentariu DB (linia 44-54 din script) | Populata de |
|
||||
|---|---|---|
|
||||
| `DISCOUNT_TVA` | TVA DISCOUNT (DISCOUNT * MAX(PROC_TVA) ARTICOLE) | `scrie_in_vanzari` |
|
||||
| `VALOARE_ACHIZITIE` | Valoare la pret achizitie articole | `scrie_in_vanzari` |
|
||||
| `TOTAL_FARA_TVA` | Total fara TVA lei | `scrie_in_vanzari` (13886), `finalizeaza_avize_lucrare` (15124) |
|
||||
| `TOTAL_TVA` | Total TVA lei | idem |
|
||||
| `TOTAL_CU_TVA` | Total cu TVA lei | `scrie_in_vanzari` (13888), `finalizeaza_avize_lucrare` (15126) |
|
||||
| `SERIE_INCASAT` | Seria chitanta/bon fiscal | `scrie_in_vanzari` (13895), din `pack_facturare.cserie_act_incasare` (setat de `scrie_incasari`) |
|
||||
| `NR_INCASAT` | Nr chitanta/bon fiscal | idem (13896) |
|
||||
| `SUMA_INCASAT` | Suma chitanta/bon fiscal | idem (13897) |
|
||||
| `TIP_INCASAT` | 11=CHITANTA, 2=BON FISCAL | idem (13898); vezi si `nTipIncasareCardBancar`=3, `nTipIncasareTichete`=5 |
|
||||
| `AVIZE` | Serie/numar avize facturate (max 1000 caractere, comentariu la linia 1490) | `scrie_corespondente_vanzari` (15421) |
|
||||
|
||||
### 9. Tipurile de factura/aviz si ramificarea codului
|
||||
|
||||
Din `VANZARI.TIP` (CASE explicit in view `fact_vfacturi2`,
|
||||
`ff_2017_03_28_01_FACTURARE.sql:89-171`) — cateva valori cheie:
|
||||
`1`=POLITICA PRETURI, `2`=CONTRACT, `3`=COMANDA, **`4`=FACT. DIN AVIZ**, `21`=AVIZ PE BAZA DE
|
||||
COMANDA, `24`=AVIZ DE RETUR, `43`=BON FISCAL MAGAZIN, etc. (lista completa la liniile citate).
|
||||
|
||||
Ramificare in VFP, `D:\ROA\ROAFACTURARE\COMUN\clase\ofacturare.vc2`, metoda
|
||||
**`do_scrie_factura`** — exista **doua copii aproape identice** ale acestei logici, in doua clase
|
||||
diferite (confirmat via `vfp_symbols.ps1 -Where`):
|
||||
- `frm_facturare_articole.do_scrie_factura` — **liniile 13981-14339**
|
||||
- `frm_facturare_articole2.do_scrie_factura` — **liniile 18004-18331**
|
||||
|
||||
Structura `DO CASE` (identica in ambele, ex. clasa 1 la liniile 14067-14174):
|
||||
- `poDate.eProforma = 1` → `{call pack_facturare.scrie_proforma(...)}` (14071)
|
||||
- `poDate.Tip = 4` → **`{call pack_facturare.scrie_factura_avize(...)}`** (14103) — "facturare din
|
||||
aviz" (comentariu 14086-14087)
|
||||
- `poDate.Tip IN (3,21,25,28,42,47)` → `{call pack_facturare.scrie_factura2(...)}` (14130) —
|
||||
"facturare pe baza de comanda / avize pe baza de comanda"
|
||||
- `Otherwise` → `{call pack_facturare.scrie_factura2(...)}` (14158) — politica de preturi/contract
|
||||
|
||||
Inainte de asta, lista de incasare `lcListaIncasare` se construieste (14012-14038) din
|
||||
`poDate.ntip_incasare` (11=chitanta, 2=bon fiscal, 3=POS/card), comun tuturor ramurilor.
|
||||
|
||||
### 10. Ramura "factura din aviz" + "achitata numerar" — ce ar trebui sa scrie si ipoteza de cauza
|
||||
|
||||
**Ce se intampla, pas cu pas** (`Tip = 4`, `ntip_incasare` in (11,2,3)):
|
||||
|
||||
1. VFP (`ofacturare.vc2:14012-14038`) construieste `lcListaIncasare` de forma
|
||||
`'11|<suma>|<id_casa>;'` (chitanta) sau `'2|...'`/`'3|...'` (bon fiscal/card) — **daca**
|
||||
`ntip_incasare` nu e in (11,2,3), `lcListaIncasare = [NULL]` (literal SQL NULL).
|
||||
2. VFP construieste `lcSql = {call pack_facturare.scrie_factura_avize(pnDiscount, serie_chit,
|
||||
nr_incasare, lcListaIncasare, id_delegat, id_masina, id_facturare, listare_detaliata,
|
||||
dataora_exp, id_agent, text_aditional, discount_evidentiat, param_aditional, ?@nid_vanzare)}`
|
||||
(14103-14115) — semnatura corespunde exact cu procedura Oracle activa
|
||||
`scrie_factura_avize` (linia **6675-7041**, care NU are `V_TOTFTVA`/`V_TOTTVA` ca prime
|
||||
argumente, spre deosebire de `scrie_factura2` — asta e corect, nu e discrepanta de parametri).
|
||||
3. In Oracle, `scrie_factura_avize` (7007-7012): `IF V_LISTA_INCASARE IS NOT NULL THEN
|
||||
pack_facturare.scrie_incasari(...)` — deci **doar daca** `lcListaIncasare` nu e literalul
|
||||
`NULL` se seteaza variabilele de pachet `cserie_act_incasare`/etc.
|
||||
4. `scrie_factura_avize` seteaza `pack_facturare.clistaid_avize := ...V_LISTAID` (7020) — lista de
|
||||
ID-uri de avize facturate, folosita ulterior de `scrie_corespondente_vanzari` pentru
|
||||
`VANZARI.AVIZE`.
|
||||
5. `scrie_factura_avize` cheama `finalizeaza_factura` (7026-7034), care cheama `scrie_in_vanzari`
|
||||
(14740) → scrie `serie_incasat`/`nr_incasat`/`suma_incasat`/`tip_incasat` din variabilele de
|
||||
pachet setate la pasul 3.
|
||||
|
||||
**La nivel de cod citit, lantul pare corect cablat** — parametrii trec prin, semnaturile se
|
||||
potrivesc, iar cele doua clase VFP (`frm_facturare_articole` si `frm_facturare_articole2`) au
|
||||
logica identica pentru aceasta ramura.
|
||||
|
||||
**IPOTEZA (cauza posibila a bug-ului, nedemonstrata prin citire de cod — necesita investigatie
|
||||
suplimentara/testare)**:
|
||||
- Daca ordinea reala de operatii difera de `ordine_operatii_facturare.txt` (ex. daca intre pasul 3
|
||||
si pasul 5 se mai apeleaza `initializeaza_date_factura` pentru alt document/lucru din aceeasi
|
||||
sesiune, inainte ca `finalizeaza_factura` sa apuce sa citeasca variabilele de pachet), fix-ul din
|
||||
03.07.2020 (linia 1876-1880, reset la NULL) ar putea sterge datele de incasare **inainte** ca
|
||||
`scrie_in_vanzari` sa le foloseasca — dar nu am gasit in codul citit un asemenea apel intercalat.
|
||||
- Alternativ: daca pe ramura aviz `scrie_corespondente_vanzari` (care scrie `VANZARI.AVIZE`) nu e
|
||||
apelata necondiționat din `finalizeaza_factura` pentru `TIP=4` (nu am verificat corpul complet al
|
||||
`finalizeaza_factura`, liniile 14723-14807, dincolo de apelul la `scrie_in_vanzari`) — merita
|
||||
verificat explicit daca acel apel exista si e neconditionat de tip.
|
||||
- Nu am verificat daca exista vreo diferenta intre `scrie_factura_avize` si
|
||||
`scrie_factura_avize_retur` (spec 667, alta ramura pentru tip retur din aviz) in privinta
|
||||
apelului `scrie_incasari`/`scrie_in_vanzari` — posibil ca bug-ul sa fie specific ramurii de retur,
|
||||
nu celei simple.
|
||||
|
||||
Recomandare pentru pasul urmator (daca se investigheaza mai departe): instrumentare/breakpoint pe
|
||||
`scrie_in_vanzari` (13468) intr-un mediu de test, pentru o factura Tip=4 platita numerar, verificand
|
||||
valorile efective ale `pack_facturare.cserie_act_incasare`/`nnumar_act_incasare`/`nsuma_incasare`/
|
||||
`ntip_doc_incasare` chiar inainte de UPDATE (13886-13898).
|
||||
|
||||
### 11. Cele doua view-uri de facturi
|
||||
|
||||
- **`fact_vfacturi`** — view-ul "original" (pe model relational, cu join-uri catre `VANZARI_DETALII`
|
||||
/ `ACT` / etc., fara denormalizare). Redefinit de multe ori de-a lungul timpului; cea mai recenta
|
||||
gasita: `D:\ROA\DATABASE\SCRIPTURI_CLAR\2023\11\ff_2023_11_17_01_COMUN.sql` (si
|
||||
`2023\02\ff_2023_02_08_01_COMUN.sql`) — nu am deschis continutul exact in acest buget.
|
||||
- **`fact_vfacturi2`** — view-ul cu totaluri **denormalizate din VANZARI** (`total_fara_tva`,
|
||||
`total_tva`, `total_cu_tva`, `serie_incasat`, `nr_incasat`, `suma_incasat`, `tip_incasat`,
|
||||
`avize` citite direct din coloanele `VANZARI`, nu recalculate din `VANZARI_DETALII`/`ACT`).
|
||||
Definit initial in **`D:\ROA\DATABASE\SCRIPTURI_CLAR\2017\03\ff_2017_03_28_01_FACTURARE.sql:59-236`**,
|
||||
cu comentariul explicit (linia 3): *"View fact_vfacturi2 - temporar, urmand a inlocui view-ul
|
||||
fact_vfacturi, dupa completarea coloanelor din vanzari pentru datele existente deja"*.
|
||||
|
||||
Separat, exista si o a doua pereche de view-uri, mai recenta si mai granulara (pe linie de
|
||||
articol, nu pe factura): **`fact_vrap_fact_articole`** / **`fact_vrap_articole_vandute`**, definite
|
||||
in `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\07\ff_2026_07_27_01_FACTURARE.sql:10-257` — acestea NU
|
||||
citesc din coloane denormalizate, ci calculeaza TVA live prin `pack_facturare.calculeaza_total_*`
|
||||
(vezi Subiect A #2). Nu sunt aceleasi cu perechea mentionata in cerinta (care pare sa se refere la
|
||||
`fact_vfacturi`/`fact_vfacturi2`), dar sunt relevante daca se cauta "view-ul cu totaluri din
|
||||
vanzari" generic.
|
||||
|
||||
---
|
||||
|
||||
## Note metodologice
|
||||
|
||||
- `PACK_SESIUNE` (motorul de rotunjire per-pret, apelat de `PACK_FACTURARE`) nu a fost gasit
|
||||
definit ca fisier separat in cautarile punctuale facute (cateva luni din 2025-2026); daca se
|
||||
continua investigatia pe rotunjire, merita o cautare dedicata `create or replace package
|
||||
pack_sesiune` in `D:\ROA\DATABASE\SCRIPTURI_CLAR`.
|
||||
- Arhiva `D:\ROA\DATABASE\SCRIPTURI_CLAR` e foarte mare (mii de fisiere, 2009-2026); cautarile de
|
||||
mai sus au fost tintite (nume de coloane/proceduri cunoscute), nu exhaustive — un `grep` complet
|
||||
pe intreg arhivul repetat timeout la 20s in unele incercari initiale.
|
||||
- Nu am gasit apeluri catre `PACK_FACTURARE` din `D:\ROA\ROAFACTURARE` propriu-zis (in afara
|
||||
`COMUN\clase\ofacturare.vc2`) — pachetul e consumat exclusiv prin acea clasa si prin
|
||||
`COMUN\programe\oproceduri_rapoarte_fact.prg`.
|
||||
164
docs/cercetare/rec_view_articole_vanzare.md
Normal file
164
docs/cercetare/rec_view_articole_vanzare.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Proiectare view Oracle pentru liniile de articole ale unei vanzari (VVANZARI_ARTICOLE)
|
||||
|
||||
Cercetare + proiectare, read-only pe baza. Decizia lui Marius (08.08.2026): view dedicat, varianta B
|
||||
din `rec_review_ancorare_s4.md` (respinsa atunci doar pentru ca insemna migrare de schema - acum
|
||||
aprobata). Inlocuieste lista de 20 coloane + join pe 4 tabele din `IncarcaArticoleFactura`
|
||||
(`COMUN\programe\ofacturare_editare.prg:201-208`).
|
||||
|
||||
## A. Precoditia VERSIUNE
|
||||
|
||||
`MARIUSM_AUTO` e la zi **pentru schema firmei (`ff_`)** pe orice ar putea atinge `VANZARI_DETALII`/
|
||||
facturare: toate scripturile `ff_` din 2015 incoace apar in `VERSIUNE`, inclusiv cele mai recente
|
||||
patru (`ff_2026_08_06_09/10/11/12`, comanda/contract, `PACK_FACTURARE`, `FACT_VFACTURI`,
|
||||
`VANZARI_BACKFILL`). Diferenta gasita fata de `SCRIPTURI_CLAR` (452 de fisiere, din care 14 `ff_`)
|
||||
e integral din 2009-2014 (dinainte de generalizarea `UpdateVersiune`) plus scripturi de diagnostic
|
||||
fara prefix de tracking (`DIAG_SPATIU_*`, ad-hoc-uri fara nume standard) - niciunul din ele nu
|
||||
atinge `VANZARI`/`VANZARI_DETALII`/facturare. Verdict: **precoditia trece**, sursa `MARIUSM_AUTO` e
|
||||
de incredere pentru acest DDL.
|
||||
|
||||
## B. Ce exista deja - niciun candidat direct refolosibil, dar un precedent util
|
||||
|
||||
Cautat in `all_views` (MARIUSM_AUTO) orice view pe `VANZARI_DETALII`/liniile unei vanzari:
|
||||
`VVANZARI_DETALII`, `VVANZARI_DETALII_TOT`, `FACT_VFACTURI_DETALII` sunt cele relevante.
|
||||
|
||||
- **`FACT_VFACTURI_DETALII`** (exportat integral) e cel mai apropiat candidat structural - selecteaza
|
||||
direct din `vanzari_detalii`, cu join-uri catre `nom_articole`/`nom_gestiuni`/`nom_valute` ca in
|
||||
proiectarea de mai jos. **Nu e reutilizabil ca atare**: `pret` si `discount_unitar` sunt
|
||||
RECALCULATE la cursul valutar curent (`ROUND(NVL(g.curs,1)*NVL(a.pret,0)/NVL(g.multiplicator,1),
|
||||
pack_sesiune.getoptiunefirma('PPRETV'))`, apel de functie PL/SQL per coloana per rand), construit
|
||||
pentru **afisare/tiparire** facturi, nu pentru editare. Pagina de editare (#6) trebuie sa lucreze
|
||||
pe valorile RAW stocate, ca la salvare (S5) sa scrie inapoi exact ce a citit - un `pret` deja
|
||||
convertit ar strica exact acest contract. Confirma insa tiparul de join corect (articol/gestiune/
|
||||
valuta) si ca genul asta de view exista deja in familia `FACT_*` pentru alt scop.
|
||||
- **`VVANZARI_DETALII`/`VVANZARI_DETALII_TOT`**: alt scop (afisare generica vanzari + utilizatori +
|
||||
politici de pret), nu au `pret_cu_tva`, `cont`, `id_valuta`, `id_gestiune`, `taxcode`, `lot` -
|
||||
nepotrivite.
|
||||
|
||||
Niciunul nu inlocuieste nevoia unui view nou - se continua cu proiectarea.
|
||||
|
||||
## C. Numele: `VVANZARI_ARTICOLE`
|
||||
|
||||
Verificat liber in `all_objects` (MARIUSM_AUTO). 17 caractere, sub limita de 30 (Oracle 10.2).
|
||||
|
||||
**Criteriul lui Marius (08.08.2026)**: numele trebuie sa pastreze prefixul familiei de vanzari,
|
||||
`vvanzari_*`, pentru ca el se uita la view-uri **alfabetic** si vrea sa vada dintr-o privire ca tine
|
||||
de vanzari. La o listare alfabetica: `VVANZARI_ARTICOLE`, `VVANZARI_DETALII`,
|
||||
`VVANZARI_DETALII_TOT`, `VVANZARI_TOT`.
|
||||
|
||||
Numele analog conventiei surorilor de pe acelasi formular (`vact_tot`, `vrul_tot`,
|
||||
`vrul_obinv_tot`) ar fi fost `vvanzari_detalii_tot`, dar e **deja ocupat** (alt view, B mai sus).
|
||||
|
||||
Numele de lucru din prima varianta a fost `VVD_TOT` (`v` + abreviere + `_tot`, aliniat cu aliasul
|
||||
VFP `tvd`), respins de Marius pe criteriul de mai sus: nu se citea ca facand parte din familie si
|
||||
cadea in alta parte a listei alfabetice.
|
||||
|
||||
## D. Coloanele - RAW, fara filtru STERS in view
|
||||
|
||||
Cele 20 de coloane consumate azi + **`id_vanzare` adaugat**: lista din
|
||||
`ofacturare_editare.prg:201-203` filtreaza pe `vd.id_vanzare` dar nu-l intoarce niciodata ca si
|
||||
coloana - omisiune reala, semnalata in misiune, acum corectata in view.
|
||||
|
||||
- **Fara conversie valutara, fara valori calculate** (spre deosebire de `FACT_VFACTURI_DETALII`) -
|
||||
editarea scrie inapoi exact ce citeste.
|
||||
- **`STERS` ramane in view ca si coloana, dar FARA filtru `WHERE sters=0` in definitie** - acelasi
|
||||
tipar ca `VACT_TOT`/`VRUL_TOT`/`VRUL_OBINV_TOT` (niciunul nu filtreaza `sters` in view, apelantul
|
||||
o face explicit). Apelantul de azi (`IncarcaArticoleFactura`) deja are `WHERE ... vd.sters = 0` -
|
||||
ramane neschimbat, doar `FROM vanzari_detalii vd ... WHERE vd.id_vanzare=... AND vd.sters=0` devine
|
||||
`FROM vvanzari_articole vd WHERE vd.id_vanzare=... AND vd.sters=0`.
|
||||
|
||||
## E. Ce s-a respins: valorile calculate `CALCULEAZA_TOTAL_FARA_TVA_FACT`/`_TVA_FACT`
|
||||
|
||||
Ambele sunt functii **in `PACK_FACTURARE`**, semnatura `(V_PRET, V_DIFERENTA, V_CURS,
|
||||
V_DISCOUNT_UNITAR, V_DISCOUNT_EVIDENTIAT, V_CANTITATE, V_PRET_CU_TVA, V_PROC_TVAV) RETURN NUMBER` -
|
||||
strict `NUMBER`, deci **apelabile din SQL** (confirmat prin `all_arguments`, fara tip PL/SQL-only).
|
||||
Exista precedent local pentru functii de pachet apelate per-rand intr-un view din aceeasi familie
|
||||
(`VRUL_TOT` cheama `PACK_SESIUNE.SUMA_RON` pe aproape fiecare coloana numerica), deci performanta nu
|
||||
e un argument respingator prin ea insasi pe un view filtrat pe `id_vanzare` (cateva linii/factura).
|
||||
|
||||
**Respins totusi, pentru acum**:
|
||||
1. `V_DISCOUNT_EVIDENTIAT` **nu e coloana pe `VANZARI_DETALII`** - e pe antet (`VANZARI.
|
||||
DISCOUNT_EVIDENTIAT`, confirmat in `all_tab_columns`). A include totalul calculat per linie ar
|
||||
cere fie un join suplimentar la `VANZARI` (umfla view-ul cu o dependenta noua doar pentru un
|
||||
parametru), fie parametrul trimis din VFP - oricum, in afara scopului Rundei 1 (doar afisare).
|
||||
2. Runda 1 (deja implementata si testata, `docs\progres.md`) **nu consuma** aceste valori - grid-ul
|
||||
e readonly, fara subtotal calculat.
|
||||
3. Nevoia reala apare la S4b/Runda 4 (`plan_06_s4_proiectare.md`, C.1-C.3) - dar acolo e vorba de
|
||||
**totalul pe DOCUMENT** (suma peste toate liniile), comparat cu `ACT`/`RUL`, nu de o coloana pe
|
||||
fiecare rand din grid. O interogare de agregare separata (sau o functie Oracle dedicata) e o
|
||||
potrivire mai buna pentru "totalul de control" decat 2 coloane calculate in view-ul de grid.
|
||||
4. **Costul amanarii e mic**: extinderea unui VIEW (`CREATE OR REPLACE`) nu e o migrare de schema in
|
||||
sensul de risc/coordonare al unei modificari de tabela - se poate adauga oricand printr-un script
|
||||
nou, fara sa afecteze datele sau consumatorii existenti ai coloanelor deja definite. Deci nu e
|
||||
nevoie sa se "prevada" acum ca sa se evite un al doilea script peste o saptamana.
|
||||
|
||||
**Recomandare pentru Runda 4**: cand S4b ajunge la implementare, se adauga fie doua coloane noi in
|
||||
`VVANZARI_ARTICOLE` (dupa un join la `VANZARI` pentru `DISCOUNT_EVIDENTIAT`), fie - preferabil - o interogare
|
||||
de agregare separata in Oracle care calculeaza direct SUMA pe document, fara sa treaca prin grid.
|
||||
Decizia ramane a lui Marius/sesiunii care implementeaza S4b, pe baza planului deja scris in
|
||||
`plan_06_s4_proiectare.md` C.1.
|
||||
|
||||
## F. Validare pe cele doua cazuri de regresie
|
||||
|
||||
Rulat direct ca `SELECT` (fara `CREATE VIEW`), corpul propus vs. interogarea de azi din
|
||||
`IncarcaArticoleFactura`, pe `MARIUSM_AUTO`:
|
||||
|
||||
- **`id_vanzare = 1050`** (`cod=1140888`, `tip=1`): **4 randuri**, valori identice rand-cu-rand intre
|
||||
interogarea veche si corpul noului view (`id_vanzare_det` 1584-1587). Coincide cu baza de regresie
|
||||
din `docs\progres.md`.
|
||||
- **`id_vanzare = 1047`** (`cod=1140885`, `tip=-12`): **2 randuri** (1578, 1579), identice intre cele
|
||||
doua interogari.
|
||||
|
||||
Ambele cazuri: zero divergenta, inclusiv pe coloanele cu `NULL` (ex. `id_gestiune`/`nume_gestiune`
|
||||
pe liniile nestocate din `id_vanzare=1047`).
|
||||
|
||||
## G. Numele coloanelor la iesire
|
||||
|
||||
Fara alias-uri noi - toate coloanele pastreaza numele lor de baza din tabelele sursa (Oracle
|
||||
foloseste automat numele coloanei cand nu exista `AS`):
|
||||
|
||||
```
|
||||
ID_VANZARE, ID_VANZARE_DET, ID_ARTICOL, CANTITATE, PRET, PRET_CU_TVA, PROC_TVAV, DISCOUNT_UNITAR,
|
||||
ID_GESTIUNE, CONT, ID_VALUTA, ID_JTVA_COLOANA, SERIE, EXPLICATIE, TAXCODE, LOT, STERS,
|
||||
DENUMIRE, CODMAT, NUME_GESTIUNE, NUME_VAL
|
||||
```
|
||||
|
||||
**Zero schimbari fata de azi** pentru `ControlSource`-urile existente ale `grdArticoleFactura`
|
||||
(`tvd.denumire`, `tvd.codmat`, etc.) - toate numele coincid cu ce se foloseste azi. Singura
|
||||
schimbare vizibila e coloana noua `tvd.id_vanzare`, disponibila dar neconsumata inca de grid.
|
||||
|
||||
## H. Numerotare script
|
||||
|
||||
`SCRIPTURI_CLAR\2026\08\` exista deja, ultimul numar folosit azi (08.08.2026, la momentul
|
||||
verificarii) e **niciunul** - nu exista fisiere `_2026_08_08_` in director (ultimele sunt din
|
||||
06.08.2026, `NN` pana la 12). **`NN=01` e liber pentru 08.08.2026**, comun tuturor prefixelor -
|
||||
de reverificat la momentul aplicarii, pentru ca sesiunea are mai multi agenti activi in paralel azi
|
||||
care ar putea consuma acelasi numar inaintea acestui script.
|
||||
|
||||
Nume final propus: **`ff_2026_08_08_01_COMUN_VVANZARI_ARTICOLE.sql`** - scriptul livrat foloseste deja acest
|
||||
nume in `exec pack_migrare.UpdateVersiune(...)`; daca sesiunea principala aloca alt `NN`, fisierul
|
||||
**si** acel apel trebuie schimbate impreuna (altfel `VERSIUNE` inregistreaza un nume care nu exista
|
||||
pe disc).
|
||||
|
||||
## I. Format script
|
||||
|
||||
`CREATE OR REPLACE VIEW` (fara `FORCE`) - verificat pe modelul cel mai recent din `SCRIPTURI_CLAR`
|
||||
(`ff_2026_08_06_11_COMUN_FACT_VFACTURI.sql`, care creeaza doua view-uri fara `FORCE`); `FORCE` nu e
|
||||
necesar oricum, toate tabelele sursa (`VANZARI_DETALII`, `NOM_ARTICOLE`, `NOM_GESTIUNI`,
|
||||
`NOM_VALUTE`) exista deja. CRLF verificat byte-safe dupa scriere (44 CRLF, 0 LF singur). Fara `;` in
|
||||
comentarii inaintea instructiunii. Se incheie cu `UpdateVersiune` + `commit`.
|
||||
|
||||
## Livrabil
|
||||
|
||||
`D:\ROA\ROAFACTURARE\docs\cercetare\ff_view_articole_vanzare.sql` - scriptul complet, **neaplicat**.
|
||||
|
||||
## Ce trebuie schimbat in VFP ca urmare (doar cand se aplica scriptul)
|
||||
|
||||
1. `COMUN\programe\ofacturare_editare.prg:201-208` (`IncarcaArticoleFactura`): inlocuieste
|
||||
`FROM vanzari_detalii vd LEFT JOIN nom_articole na ... LEFT JOIN nom_gestiuni ng ... LEFT JOIN
|
||||
nom_valute nv ...` cu `FROM vvanzari_articole vd`, pastrand neschimbat `WHERE vd.id_vanzare = ... AND
|
||||
vd.sters = 0` si toata lista de coloane din `SELECT` (numele raman identice).
|
||||
2. Fallback-ul `CREATE CURSOR tvd (...)` (`:214-216`) si duplicatul din `omodificari.vc2` (~14076,
|
||||
semnalate deja ca duplicare in `rec_review_ancorare_s4.md`) **nu se ating** de aceasta schimbare -
|
||||
raman neschimbate structural, doar sursa `SELECT`-ului se simplifica.
|
||||
3. **Opional**, daca se doreste sa se profite de coloana noua `id_vanzare`: nu e necesar niciun
|
||||
consum imediat in VFP - grid-ul nu are nevoie de ea (id-ul e deja cunoscut din parametrul functiei).
|
||||
207
docs/cercetare/rec_watchdog_vfp.md
Normal file
207
docs/cercetare/rec_watchdog_vfp.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# Watchdog VFP + diagnostic blocaj "View Parameter" (test_page3_articole.prg)
|
||||
|
||||
## 1. Utilitarul: `COMUN\utile\Teste\watchdog_vfp.ps1`
|
||||
|
||||
Lanseaza `vfp9.exe -A -T "<script>"`, polleaza la ~700ms ferestrele TOP-LEVEL ale procesului
|
||||
(`EnumWindows`+`GetWindowThreadProcessId`, filtrate pe PID). Fereastra principala VFP se identifica
|
||||
prin `Process.MainWindowHandle` (.NET) - **nu** dupa numele clasei: VFP inregistreaza clase diferite
|
||||
prefixate `vfp9...` atat pentru shell-ul principal (`vfp99400000`) cat si pentru dialogurile lui
|
||||
proprii (`vfp994000002` pentru "View Parameter") - o clasificare pe clasa a lasat "View Parameter"
|
||||
nedetectat la prima incercare (corectat).
|
||||
|
||||
Pentru fiecare fereastra noua (diferita de `MainWindowHandle`): captura PNG (`PrintWindow`, fallback
|
||||
`CopyFromScreen` daca iese neagra) + dump text (titlu, clasa, si textul/clasa fiecarui control copil
|
||||
via `WM_GETTEXT`, cross-proces). Cu `-AutoDismiss`: cauta un buton copil "Cancel"/"Anulare" si
|
||||
trimite `BM_CLICK`; altfel incearca, in ordine, `WM_COMMAND IDCANCEL` -> ESCAPE ca MESAJ
|
||||
(`WM_KEYDOWN`/`WM_KEYUP`, tintit pe handle) -> `WM_CLOSE`.
|
||||
|
||||
**REGULA OBLIGATORIE, incalcata initial si corectata**: watchdog-ul NU are voie sa foloseasca INPUT
|
||||
REAL de tastatura/mouse (`keybd_event`, `SetForegroundWindow`, `SendInput`, `mouse_event`) - masina e
|
||||
PARTAJATA cu utilizatorul. Prima versiune folosea `SetForegroundWindow`+`keybd_event(ESCAPE)` ca
|
||||
fallback pentru dialogurile proprii VFP owner-drawn (fara controale copil reale) - **acest input NU
|
||||
are tinta, ajunge in orice fereastra are focus pe masina in acel moment, indiferent al cui proces
|
||||
e**. **Fapt clarificat de team-lead, dupa investigare**: in acest caz concret, ESC-ul a aterizat de
|
||||
fapt in PROPRIUL NOSTRU proces de test (eroarea "Variable 'GNAN' is not found" vazuta imediat inainte
|
||||
de "Execution was canceled by the user" e chiar semnatura testului nostru) - **nu in sesiunea lui
|
||||
Marius**, deci de fapt nu s-a intrerupt munca nimanui de data asta. Asta NU schimba regula: mecanismul
|
||||
tot nu are tinta si putea la fel de usor sa ajunga in aplicatia de productie (`roafacturare.exe`/
|
||||
`roacont.exe`) daca utilizatorul avea focus acolo in acea clipa - o formulare anterioara aici spunea
|
||||
gresit ca ar fi afectat sesiunea utilizatorului, corectata acum. **Scos complet** din cod (nu mai
|
||||
exista nicio linie `keybd_event`/`SetForegroundWindow` in `watchdog_vfp.ps1`). Consecinta: pentru
|
||||
dialogurile owner-drawn care nu raspund la mesaje tintite, `-AutoDismiss` **esueaza cinstit** (dialogul
|
||||
ramane deschis pana la `-TimeoutSec`, apoi procesul e omorat) - captura (PNG+dump text) ramane de incredere,
|
||||
dismiss-ul nu e garantat pentru acest tip de dialog. Procesul e omorat mereu la iesire (`finally`),
|
||||
nu ramane niciodata viu.
|
||||
|
||||
Validat intai pe caz banal: `COMUN\utile\Teste\watchdog_selftest.prg` (`MESSAGEBOX` cu OK/Cancel) -
|
||||
detectie, captura, dump text si auto-dismiss confirmate corecte inainte de a-l rula pe cazul real.
|
||||
|
||||
Utilizare: `powershell -ExecutionPolicy Bypass -File watchdog_vfp.ps1 -Script "<test.prg>" -AutoDismiss [-TimeoutSec 90] [-MaxDialogs 10] [-OutDir <cale>]`.
|
||||
|
||||
## 2. Dialogurile capturate pe `test_page3_articole.prg`
|
||||
|
||||
**Dialog 0** - nativ VFP, clasa `vfp994000002`, titlu **"View Parameter"**, text **"Enter the value
|
||||
for gnAn:"** (fara controale copil reale - owner-drawn). Screenshot:
|
||||
`COMUN\utile\Teste\editare_factura\watchdog_out\test_page3_articole_dialog0.png`.
|
||||
|
||||
**Dialog 1** (apare doar cand dialog 0 e inchis prin ESCAPE real, care functioneaza) - "Open" Win32
|
||||
standard, filtru "Table/DBF (*.dbf)", folder implicit `ROACONT` (working directory-ul mediului de
|
||||
test, mostenit din `test_init_env_auto.prg`). Screenshot:
|
||||
`COMUN\utile\Teste\editare_factura\watchdog_out\test_page3_articole_dialog1.png`.
|
||||
|
||||
## 3. PROGRAM()/LINENO() din log (dupa Cancel pe dialog 0)
|
||||
|
||||
Din `test_page3_articole_log.txt`, PROGRAM()=`VERIFICA_PAGECOUNT_FORM` (procedura de test) pe
|
||||
liniile din jurul apelului `loForm = Createobject([frm_modific2024], lnIdSet)`:
|
||||
|
||||
```
|
||||
EROARE 1 [VERIFICA_PAGECOUNT_FORM:165] File 'crsjtvatemp.dbf' does not exist.
|
||||
EROARE 1924 [VERIFICA_PAGECOUNT_FORM:166..173] LOFORM is not an object. (cascada, zgomot)
|
||||
```
|
||||
|
||||
## 4. Experimente de izolare (cerute de team-lead) - **INFIRMA ipoteza initiala**
|
||||
|
||||
Ipoteza initiala din aceasta sectiune ("`SQLEXEC` din `update_jtva_coloane` nu rezolva `?gnAn`") era
|
||||
o **deductie**, nu o masuratoare - team-lead a cerut-o verificata direct, corect. Trei experimente
|
||||
ieftine, in ordine:
|
||||
|
||||
**Experiment A - "chiar exista in acel moment?"** `TYPE('gnAn')`/`TRANSFORM(gnAn)` puse imediat
|
||||
**INAINTE** de apelul `update_jtva_coloane` (linia 161 curenta, nu inainte de `Createobject` cum
|
||||
fusese verificat prima data):
|
||||
|
||||
```
|
||||
EROARE 12 [VERIFICA_PAGECOUNT_FORM:161] Variable 'GNAN' is not found.
|
||||
```
|
||||
|
||||
- Eroare aparuta DOAR la primul apel al `verifica_pagecount_form` (`cod=1140888`), inainte sa se
|
||||
ajunga la `update_jtva_coloane`. **Rezultat: `gnAn` e deja invizibila INAINTE ca `update_jtva_coloane`
|
||||
sa fie apelata** - markerele `?gnAn`/`?gnLuna` din `updateserver.prg:597` nu pot fi (macar nu
|
||||
singure) cauza, contrazice ipoteza initiala.
|
||||
|
||||
**Experiment B - "se reproduce izolat, fara nimic din S4?"** Script nou,
|
||||
`COMUN\utile\Teste\editare_factura\test_repro_izolat_gnan.prg`: DOAR `test_init_env_auto` +
|
||||
`update_jtva_coloane("", "crsJtvaTemp", 6)`, fara `IncarcaCursoareModificareNota`, fara
|
||||
`frm_modific2024`, fara nimic din PAGE3. Rezultat:
|
||||
|
||||
```
|
||||
TYPE(gnAn)=N TRANSFORM(gnAn)=2026 TYPE(gnLuna)=N TRANSFORM(gnLuna)=8
|
||||
dupa update_jtva_coloane: Used(crsJtvaTemp)=.T. Reccount=120
|
||||
done
|
||||
```
|
||||
|
||||
**NU reproduce.** Zero dialog, exit curat, cursorul se creeaza corect cu 120 randuri.
|
||||
`update_jtva_coloane` singura, chemata imediat dupa initul mediului, functioneaza perfect -
|
||||
**nu e o capcana preexistenta a harness-ului si nici o vina proprie a functiei in izolare**.
|
||||
Rerulat identic dupa scoaterea input-ului real din watchdog (vezi sectiunea 1) - acelasi rezultat,
|
||||
deci reconfirmat, nu era un artefact al mecanismului de dismiss.
|
||||
|
||||
**Experiment C - oprit inainte de a-l rula.** Premisa lui ("copiaza corpul lui `update_jtva_coloane`
|
||||
cu concatenare in loc de `?param`, ca sa confirmi mecanismul") presupune ca vina e in legarea
|
||||
`SQLEXEC` a functiei - exact ce B tocmai a infirmat. Nu are sens sa continue in forma ceruta initial
|
||||
fara o noua directie.
|
||||
|
||||
## 5. Cauza CONFIRMATA prin bisectie (nu doar deductie)
|
||||
|
||||
Bisectie ceruta de team-lead: `TYPE('gnAn')`/`TRANSFORM(gnAn)` logat in **doua straturi** - (a) in
|
||||
programul principal, intre fiecare apel de nivel superior, si (b) ca **prima linie** in interiorul
|
||||
fiecarei proceduri (`verifica_vanzare_nota`, `verifica_coliziune_cod`, `verifica_pagecount_form`).
|
||||
Helper `bisect_log_gnan` (nou, la coada `test_page3_articole.prg`) - TYPE() e sigur necoditionat,
|
||||
TRANSFORM() doar daca TYPE()<>'U', ca sa nu produca o eroare noua care ar intrerupe bisectia.
|
||||
|
||||
Rezultat brut (`test_page3_articole_log.txt`):
|
||||
|
||||
```
|
||||
[BISECT] main: dupa test_init_env_auto :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] verifica_vanzare_nota ENTRY cod=1140888 :: TYPE(gnAn)=U gnAn=(U)
|
||||
[BISECT] main: dupa verifica_vanzare_nota #1 (cod=1140888) :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] verifica_vanzare_nota ENTRY cod=1140885 :: TYPE(gnAn)=U gnAn=(U)
|
||||
[BISECT] main: dupa verifica_vanzare_nota #2 (cod=1140885) :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] verifica_vanzare_nota ENTRY cod=1125486 :: TYPE(gnAn)=N gnAn=2026 <- diferit!
|
||||
[BISECT] main: dupa verifica_vanzare_nota #3 (cod=1125486) :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] verifica_coliziune_cod ENTRY :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] main: dupa verifica_coliziune_cod :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] main: inainte de verifica_pagecount_form :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] verifica_pagecount_form ENTRY cod=1140888 :: TYPE(gnAn)=U gnAn=(U)
|
||||
[BISECT] verifica_pagecount_form inainte de update_jtva_coloane :: TYPE(gnAn)=U gnAn=(U)
|
||||
```
|
||||
|
||||
**Tiparul e limpede si consecvent**: `gnAn` e INTOTDEAUNA valid (`N`, `2026`) in scope-ul PRINCIPAL,
|
||||
la fiecare checkpoint, fara exceptie - deci **NU e "eliberata"** (nu e `CLEAR ALL`/`CLEAR MEMORY`/
|
||||
`RELEASE ALL EXTENDED` pe undeva). E **`'U'` STRICT la intrarea in proceduri apelate cu `DO ... WITH`
|
||||
in care `gnAn`/`gnLuna` sunt trecute NEPARANTEZATE ca argumente**, si redevine valid imediat ce
|
||||
procedura respectiva se termina si controlul revine in principal. Corelatia e exacta cu sintaxa
|
||||
apelului, nu cu ce face procedura pe dinauntru:
|
||||
|
||||
- `verifica_vanzare_nota` apelul #1/#2 (`gnAn` -> `U`): call-site-urile trec `gnAn, gnLuna` DIRECT -
|
||||
`test_page3_articole.prg:34` (`DO verifica_vanzare_nota WITH 1140888, gnAn, gnLuna, ...`) si
|
||||
`test_page3_articole.prg:36` (`... WITH 1140885, gnAn, gnLuna, ...`).
|
||||
- `verifica_vanzare_nota` apelul #3 (`gnAn` ramane `N`): `test_page3_articole.prg:38` trece
|
||||
`2008, 2` LITERAL, nu `gnAn`/`gnLuna`.
|
||||
- `verifica_coliziune_cod` (`gnAn` ramane `N`): `test_page3_articole.prg:42` nu trece deloc
|
||||
`gnAn`/`gnLuna` (doar `lcLog`).
|
||||
- `verifica_pagecount_form` primul apel (`gnAn` -> `U`, **exact scenariul blocat**):
|
||||
**`test_page3_articole.prg:47`** - `DO verifica_pagecount_form WITH 1140888, gnAn, gnLuna, 'A (factura reala)', lcLog, 3, .T.`.
|
||||
|
||||
**Mecanismul**: `DO <procedura> WITH <arg1>, <arg2>, ...` (stilul vechi, folosit peste tot in acest
|
||||
script) trece variabilele de memorie **BY REFERENCE** implicit (`SET UDFPARMS` e `REFERENCE` in mod
|
||||
implicit VFP) - `LPARAMETERS tnAn, tnLuna` din procedura primitoare devin ALIAS-uri directe pe
|
||||
storage-ul lui `gnAn`/`gnLuna`, iar numele ORIGINAL devine inaccesibil (`TYPE()='U'`) **pe toata
|
||||
durata apelului**, exact cat tine executia procedurii - confirmat empiric de simetria perfecta
|
||||
"intra U, revine N" la fiecare din cele 3 perechi de apeluri afectate.
|
||||
|
||||
**Clasificare in termenii cerutii de team-lead**: e **"umbrire de scope"** (categoria 2), NU
|
||||
"eliberare" (categoria 1) - dar mecanismul exact nu e o coliziune de nume `PRIVATE`/`LOCAL` in corpul
|
||||
procedurii (team-lead avea deja dreptate: `verifica_pagecount_form` nu are `gnAn` in `LOCAL`, si nu
|
||||
exista `PRIVATE gnAn`/`LOCAL gnAn` nicaieri in `COMUN\programe`) - **umbrirea vine din SINTAXA
|
||||
APELULUI** (`DO...WITH` fara paranteze in jurul lui `gnAn`/`gnLuna`), nu din declaratiile procedurii
|
||||
apelate.
|
||||
|
||||
**Statement-ul vinovat exact, cu fisier:linie**: `COMUN\utile\Teste\editare_factura\test_page3_articole.prg:47`.
|
||||
|
||||
**IMPLICATIE IMPORTANTA**: acesta e un tipar din **SCRIPTUL DE TEST**, nu din fluxul real al
|
||||
aplicatiei - `do_editare_factura` (codul de productie) nu trece prin `verifica_pagecount_form`
|
||||
(helper propriu testului). Team-lead a confirmat verdictul: **e strict un defect de harness** -
|
||||
`updateserver.prg`, `omodificari.*` si codul S4 sunt toate nevinovate.
|
||||
|
||||
**Remediu APLICAT de team-lead** (3 linii, sub pragul lui de editare directa): argumentele
|
||||
`gnAn`/`gnLuna` sunt acum parantezate - `(gnAn)`, `(gnLuna)` - la liniile 37, 39 si 50 din
|
||||
`test_page3_articole.prg` (parantezele forteaza trecere PRIN VALOARE in loc de PRIN REFERINTA),
|
||||
cu un comentariu explicativ deasupra primei aparitii. Nerulat inca de mine (interzis explicit -
|
||||
suita o ruleaza team-lead-ul dupa eliberarea `.fxp`-ului).
|
||||
|
||||
**Remediul din rundele anterioare ale acestui raport (concatenare in loc de `?gnAn`/`?gnLuna` in
|
||||
`updateserver.prg:597`) ramane infirmat** - nu era cauza. `updateserver.prg` nu a fost si nu e atins.
|
||||
|
||||
## 6. Fisiere atinse
|
||||
|
||||
- **Nou**: `COMUN\utile\Teste\watchdog_vfp.ps1`, `COMUN\utile\Teste\watchdog_selftest.prg`,
|
||||
`COMUN\utile\Teste\editare_factura\test_repro_izolat_gnan.prg` (experimentul B, izolat).
|
||||
- **Modificat**: `COMUN\utile\Teste\editare_factura\test_page3_articole.prg`
|
||||
- linia 176 (`update_jtva_coloane(..., 6)`, ramane - fix necesar pt. indexul `id_jtva`, independent
|
||||
de defectul de mai jos);
|
||||
- `PROCEDURE bisect_log_gnan` (noua, la coada fisierului) + apeluri `DO bisect_log_gnan WITH ...`
|
||||
inserate in principal (intre apelurile de nivel superior) si ca prima linie in fiecare procedura
|
||||
- ramase in cod, sunt dovada bisectiei;
|
||||
- **liniile 37, 39, 50 - remediul APLICAT de team-lead**: `gnAn`/`gnLuna` parantezate (`(gnAn)`,
|
||||
`(gnLuna)`), forteaza trecere prin valoare in loc de prin referinta in `DO...WITH`.
|
||||
- **Neatins**: `COMUN\clase\omodificari.vc2/.vcx/.vct`, `COMUN\programe\updateserver.prg` (ambele
|
||||
infirmate ca posibila cauza, vezi sectiunea 5).
|
||||
- Artefacte de rulare (`watchdog_out\*.png/.log`, `*_log.txt`) raman pe disc ca dovada; se pot sterge
|
||||
cu `curatenie.ps1` la finalul lucrarii.
|
||||
|
||||
## 7. Stare la data acestui raport
|
||||
|
||||
**Cauza confirmata prin bisectie (sectiunea 5) si remediul APLICAT de team-lead** (paranteze la
|
||||
liniile 37/39/50). **Nerulat inca** de nimeni dupa aplicarea remediului - team-lead ruleaza suita
|
||||
separat, dupa eliberarea `.fxp`-ului (nu s-a mai relansat testul in aceasta sesiune, per interdictia
|
||||
primita). Ramane deschis, pentru cine continua:
|
||||
|
||||
1. Confirma cu o rulare ca remediul chiar elimina dialogul si `verifica_pagecount_form` trece PASS
|
||||
pe `PageCount=3`/`lAreArticoleVanzari=.T.` pentru cod=1140888.
|
||||
2. Optional: verifica daca fluxul REAL de productie (`do_editare_factura` in `ofacturare_comun.vc2`)
|
||||
are undeva acelasi tipar `DO...WITH <variabila PUBLIC>` NEPARANTEZAT inainte de un `?param` in
|
||||
SQLEXEC - team-lead a verdictuit "defect de harness", dar asta ramane neverificat exhaustiv pe
|
||||
codul de productie.
|
||||
3. Watchdog-ul (`watchdog_vfp.ps1`) ramane instrumentul de verificat orice ipoteza noua fara sa se
|
||||
agate procesul si FARA input real (regula obligatorie, sectiunea 1) - reutilizabil pentru orice
|
||||
alt blocaj similar in suita.
|
||||
55
docs/cercetare/s10_curata_versiune.sql
Normal file
55
docs/cercetare/s10_curata_versiune.sql
Normal file
@@ -0,0 +1,55 @@
|
||||
-- S10 - curatare istoric TABELA VERSIUNE, MARIUSM_AUTO/ROA_CENTRAL
|
||||
-- Scop: cele 5 scripturi ff_2026_08_06_* au fiecare mai multe inregistrari in VERSIUNE,
|
||||
-- din aplicari succesive pe masura ce au fost extinse in cursul zilei de 06.08.2026.
|
||||
-- Fara impact functional (versiune_db.txt si aplicarea DDL nu depind de numarul de randuri),
|
||||
-- doar istoric zgomotos. Pastreaza UN singur rand per script (cel cu ID_VERSIUNE maxim, adica
|
||||
-- ultima aplicare - starea finala reala a scriptului), sterge restul.
|
||||
--
|
||||
-- NU S-A RULAT. Propunere pentru aprobare - stergerea de istoric e decizie de om, iar
|
||||
-- MARIUSM_AUTO e schema de dezvoltare partajata.
|
||||
|
||||
-- 1) Verificare inainte de stergere: cate randuri per script, azi
|
||||
select script_final, count(*) as nr_inregistrari
|
||||
from versiune
|
||||
where script_final in (
|
||||
'ff_2026_08_06_02_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_03_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_04_COMUN_VANZARI_COMANDA_CONTRACT.sql',
|
||||
'ff_2026_08_06_05_COMUN_FACT_VFACTURI.sql',
|
||||
'ff_2026_08_06_06_COMUN_VANZARI_BACKFILL.sql'
|
||||
)
|
||||
group by script_final
|
||||
order by script_final;
|
||||
|
||||
-- Stare masurata 06.08.2026: _02=2, _03=1 (nimic de sters), _04=2, _05=4, _06=5 (14 randuri total,
|
||||
-- 9 de sters, ramanand 5 - unul per script).
|
||||
|
||||
-- 2) Stergere: pastreaza doar randul cu ID_VERSIUNE maxim per script (ultima aplicare)
|
||||
delete from versiune v
|
||||
where v.script_final in (
|
||||
'ff_2026_08_06_02_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_03_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_04_COMUN_VANZARI_COMANDA_CONTRACT.sql',
|
||||
'ff_2026_08_06_05_COMUN_FACT_VFACTURI.sql',
|
||||
'ff_2026_08_06_06_COMUN_VANZARI_BACKFILL.sql'
|
||||
)
|
||||
and v.id_versiune < (
|
||||
select max(v2.id_versiune)
|
||||
from versiune v2
|
||||
where v2.script_final = v.script_final
|
||||
);
|
||||
|
||||
-- 3) Verificare dupa stergere: fiecare script din lista trebuie sa aiba exact 1 rand
|
||||
select script_final, count(*) as nr_inregistrari
|
||||
from versiune
|
||||
where script_final in (
|
||||
'ff_2026_08_06_02_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_03_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_04_COMUN_VANZARI_COMANDA_CONTRACT.sql',
|
||||
'ff_2026_08_06_05_COMUN_FACT_VFACTURI.sql',
|
||||
'ff_2026_08_06_06_COMUN_VANZARI_BACKFILL.sql'
|
||||
)
|
||||
group by script_final
|
||||
order by script_final;
|
||||
|
||||
-- commit; -- de dat manual, dupa verificarea pasului 3
|
||||
296
docs/cercetare/valuta_si_curs.md
Normal file
296
docs/cercetare/valuta_si_curs.md
Normal file
@@ -0,0 +1,296 @@
|
||||
# Cercetare: `poDate.in_valuta`, `Clb_zi_curs` si cele doua concepte de valuta
|
||||
|
||||
Investigatie read-only (fara editari, fara `git_sync.ps1`/`txt2vcx.ps1`, fara commit). Sursa: cache
|
||||
text `.vc2`/`.prg` din `COMUN\clase\ofacturare.vc2`, `COMUN\programe\ofacturare.prg`,
|
||||
`COMUN\programe\ofacturare_comun.prg`, `COMUN\programe\ofacturare_stoc.prg`,
|
||||
`COMUN\programe\oproceduri_curs.prg`, plus pachetul Oracle
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql` (copie pe disc,
|
||||
alta numerotare decat baza). Reutilizeaza si confirma cercetari anterioare din
|
||||
`docs\cercetare\rec_cale_vanzari_detalii.md` si `docs\cercetare\rec_consumatori_vanzari.md`.
|
||||
|
||||
---
|
||||
|
||||
## 1. `poDate.in_valuta` — unde se seteaza si din ce
|
||||
|
||||
**Concluzie**: `in_valuta` e determinat **o singura data**, la `Init`, exclusiv din **tipul
|
||||
documentului** (`tnTip`) plus o lista fixa de `id_set` — niciodata din alegerea manuala a unei
|
||||
valute in antet si niciodata resetat ulterior. E o proprietate a *tipului de factura* (Invoice /
|
||||
credit note / retur valuta / factura fiscala valuta pe contract), nu a faptului ca articolele au
|
||||
preturi in valuta.
|
||||
|
||||
**Dovezi**:
|
||||
- Valoare implicita `0`: `COMUN\programe\ofacturare_comun.prg:165` (`in_valuta = 0`, in blocul de
|
||||
proprietati al obiectului `poDate`).
|
||||
- Singurul loc care il seteaza pe `1`, in `Procedure Init`:
|
||||
```
|
||||
ofacturare_comun.prg:248-250
|
||||
If Inlist(tnIdSet,223,225,226,227,271) OR INLIST(m.tnTip, 5,6,7,9,10,52)
|
||||
.in_valuta = 1
|
||||
Endif
|
||||
```
|
||||
- Legenda tipurilor (comentariu din `frm_date_factura.Init`), `ofacturare.vc2:9571-9582`:
|
||||
`1`=lista preturi, `2`=contract, `3`=comanda, `4`=aviz, `5`=Invoice lista preturi, `6`=Invoice
|
||||
contract, `7`=credit note, `8`=retur lei, `9`=retur valuta, `48`=avize valoric, `52`=Factura
|
||||
fiscala valuta contract. Tipul `10` nu are comentariu explicit in acest bloc (adaugat separat,
|
||||
v2.0.56, ca variatie de tip 1/5).
|
||||
- Nicio alta cale de scriere pe `in_valuta` in `.vc2`/`.prg` din COMUN — verificat cu grep
|
||||
(`\.in_valuta\s*=\s*[01]`) pe intreg `ofacturare.vc2` si `ofacturare.prg`: restul potrivirilor
|
||||
sunt toate **citiri** (`If poDate.in_valuta = 1 ...`), nu atribuiri. `ofacturare_stoc.prg:549`
|
||||
(`poDate.in_valuta = in_valuta`) e o cale alternativa (facturare "din stoc") care primeste
|
||||
parametrul `in_valuta` deja calculat in amonte, cu aceeasi semantica.
|
||||
- Consecinta directa, confirmata de cod: alegerea manuala a unei valute pentru document (control
|
||||
`ct_clb_valuta`) nu poate schimba `in_valuta` — controlul insusi e eliminat din formular cand
|
||||
`in_valuta = 0` (`ofacturare.vc2:9725-9728`), deci userul nu are cum sa-l "aleaga" pe o factura
|
||||
care nu e deja de tip valuta.
|
||||
|
||||
---
|
||||
|
||||
## 2. Campul „Data curs valutar" (`Clb_zi_curs`) — unde e definit si cand e eliminat azi
|
||||
|
||||
**Concluzie**: campul e eliminat **doar** pentru facturi de retur (`tip` 8 sau 9), niciodata pe
|
||||
baza de `in_valuta`. **Da, azi campul apare si pe facturile in lei** (`in_valuta=0`) de orice alt
|
||||
tip — comportament confirmat explicit prin simetrie de cod: imediat dupa blocul de retur, exista un
|
||||
bloc separat care elimina `ct_clb_valuta` cand `in_valuta=0`, dar echivalentul lipseste pentru
|
||||
`clb_zi_curs`.
|
||||
|
||||
**Dovezi** (identificarea claselor facuta cu `vfp_symbols.ps1 -Where`):
|
||||
|
||||
| Clasa | Interval | `Clb_zi_curs` definit | Eliminat azi? |
|
||||
|---|---|---|---|
|
||||
| `frm_date_aviz` | `ofacturare.vc2:6566-7618` | `:6727-6740` (caption "Data cursului valutar") | Niciodata — zero `RemoveObject`/conditionare pe `in_valuta` in toata clasa (verificat exhaustiv) |
|
||||
| `frm_date_aviz_lucrare` | `:7620-8201` | `:7787-7801` | Niciodata; in plus, validare **necondiționata**: `:8076` `Case Empty(Nvl(poDate.zi_curs,{}))` fara nicio garda pe `in_valuta` (spre deosebire de `frm_date_factura`, vezi mai jos) |
|
||||
| `frm_date_factura` | `:8482-9869` | `:8701-8714` (caption "Data curs valutar") | **Doar** pentru `tip` 8/9, in `Init`: |
|
||||
|
||||
```
|
||||
ofacturare.vc2:9717-9722 (frm_date_factura.Init)
|
||||
*!* modificare v 2.0.56
|
||||
If Inlist(poDate.tip, 8, 9)
|
||||
lnHeight = lnHeight - .clb_zi_curs.Height
|
||||
laPozitii(.clb_zi_curs.TabIndex, 2) = 1
|
||||
.RemoveObject('clb_zi_curs')
|
||||
Endif
|
||||
*!* modificare v 2.0.56 ^
|
||||
|
||||
ofacturare.vc2:9725-9728 (imediat dupa, in ACEEASI metoda)
|
||||
If poDate.in_valuta = 0
|
||||
lnHeight = lnHeight - .ct_clb_valuta.Height
|
||||
laPozitii(.ct_clb_valuta.TabIndex, 2) = 1
|
||||
.RemoveObject('ct_clb_valuta')
|
||||
```
|
||||
|
||||
Cele doua blocuri sunt adiacente si scrise dupa acelasi tipar (inaltime, `laPozitii`,
|
||||
`RemoveObject`) — dovada ca autorul original a tratat `ct_clb_valuta` (selectorul de valuta) ca
|
||||
dependent de `in_valuta`, dar **nu** a facut acelasi lucru pentru `clb_zi_curs`. Validarea de
|
||||
completare e de asemenea asimetrica: `ofacturare.vc2:9484`
|
||||
(`Case poDate.in_valuta = 1 And Empty(Nvl(poDate.zi_curs,{})) And ...`) cere data curs **doar** cand
|
||||
`in_valuta=1`, in timp ce `frm_date_aviz_lucrare` (`:8076`) o cere mereu — inconsistenta intre cele
|
||||
doua forme, de retinut daca regula noua trebuie aplicata uniform.
|
||||
|
||||
Nota: `frm_facturare_articole2` (clasa separata, `:15741-19355`) are propriul label "Curs valutar"
|
||||
(control diferit, `:16285-16299`), tratat la punctul 3/5 — nu e acelasi camp cu `Clb_zi_curs` din
|
||||
antet, dar citeste aceeasi `poDate.zi_curs`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Cele doua concepte, in cod — confirmate distinct
|
||||
|
||||
**Concluzie**: da, distinctia exista clar in cod, pe doua axe independente:
|
||||
- **(a) valuta de document**: `poDate.in_valuta` / `poDate.Curs` / `poDate.multiplicator` /
|
||||
`poDate.id_valuta` — un singur curs, al documentului intreg, folosit cand tot documentul e emis
|
||||
in valuta.
|
||||
- **(b) articol cu pret in valuta pe document in lei**: `poArticol.tip_valuta = 1` (proprietate a
|
||||
politicii de pret a articolului, independenta de `poDate.in_valuta`), cu preturile brute in
|
||||
valuta pastrate in `poArticol.pretftva_val`/`pretctva_val`/`pretd` + `id_valuta_d`, convertite in
|
||||
lei **client-side, in VFP**, folosind cursul zilei `poDate.zi_curs`.
|
||||
|
||||
**Dovezi — conversia in lei pentru cazul (b)**:
|
||||
```
|
||||
ofacturare.vc2:1989 poArticol.pretftva = Round(poArticol.pretftva_val * poArticol.Curs / poArticol.multiplicator, gnPPretV)
|
||||
ofacturare.vc2:2953 poArticol.pretftva = Round(poArticol.pretftva_val * poArticol.Curs / poArticol.multiplicator, gnPPretV)
|
||||
ofacturare.vc2:2017 poArticol.pretctva = Round(poArticol.pretctva_val * poArticol.Curs / poArticol.multiplicator, gnPPretV)
|
||||
```
|
||||
`poArticol.Curs`/`multiplicator` (nu e alt curs decat cel al zilei documentului) provin din cursorul
|
||||
`crscursuri`, incarcat explicit **cand documentul e in lei** — exact pentru articolele cu preturi in
|
||||
valuta:
|
||||
```
|
||||
ofacturare.prg:407-418 (identic si la :941-947)
|
||||
If poDate.in_valuta = 1
|
||||
Select Distinct Curs, nume_val, id_valuta, multiplicator From (lcCursor) ... Where tip_valuta = 1 ... Into Cursor crscursuri
|
||||
Select crscursuri
|
||||
poDate.Curs = Curs
|
||||
poDate.multiplicator = multiplicator
|
||||
Else
|
||||
citeste_cursuri_zi(poDate.zi_curs)
|
||||
If Reccount('crscursuri') = 0
|
||||
Use In crscursuri
|
||||
Endif
|
||||
Endif
|
||||
```
|
||||
`citeste_cursuri_zi` (`COMUN\programe\oproceduri_curs.prg:113-124`) construieste `crscursuri` cu
|
||||
**toate** cursurile valabile la `tdDataCurs` (`= poDate.zi_curs`):
|
||||
```
|
||||
oproceduri_curs.prg:117-118
|
||||
lcSql = [select nume_val,curs,id_valuta,multiplicator from ] + gcS + [.vcurs where data <= ... and data2 >= ...]
|
||||
```
|
||||
Cursorul e apoi afisat direct pe grila de selectie a articolelor, cu eticheta construita din
|
||||
`poDate.zi_curs`, **indiferent de `in_valuta`**:
|
||||
```
|
||||
ofacturare.vc2:15097-15098 si 19004-19005 (frm_facturare_articole2)
|
||||
If !Empty(Nvl(poDate.zi_curs, {}))
|
||||
Thisform.lb_cursuri.Caption = "Curs valutar " + Iif(!Inlist(poDate.tip, 8, 9), "(" + Dtoc(poDate.zi_curs) + ")", "")
|
||||
```
|
||||
Grila/eticheta apar doar daca `crscursuri` are randuri (`ofacturare.vc2:15092`/`19000`), ceea ce se
|
||||
intampla si pe un document in lei, daca exista macar un articol cu politica in valuta.
|
||||
|
||||
**`VANZARI` vs `VANZARI_DETALII` — ce se stocheaza**:
|
||||
- `VANZARI` (document): coloane proprii `CURS`/`ID_VALUTA`/`MULTIPLICATOR` — cursul/valuta **doar
|
||||
ale documentului**, populate din `poDate.Curs`/`id_valuta`/`multiplicator` (relevante cand
|
||||
`in_valuta=1`).
|
||||
- `VANZARI_DETALII` (linie): **nu are coloana `CURS`** — confirmat din `all_tab_columns`
|
||||
(`docs\cercetare\rec_cale_vanzari_detalii.md:171-175`) si din SQL-ul live al pachetului, care
|
||||
reface cursul liniei prin JOIN, nu dintr-o coloana proprie:
|
||||
```
|
||||
PACK_FACTURARE.sql:3773-3778 (identic la :4034-4036, :6393-6396, :6571-6573)
|
||||
LEFT JOIN VANZARI_CURSURI B1 ON A1.ID_VANZARE = B1.ID_VANZARE AND A1.ID_VALUTA = B1.ID_VALUTA
|
||||
```
|
||||
Linia stocheaza insa `PRET` (pretul efectiv, in lei, folosit pe factura) **si** `PRETD` +
|
||||
`ID_VALUTAD` (pretul brut in valuta si valuta originii, pastrate ca referinta/audit) — vezi
|
||||
INSERT-ul din `adauga_articol_factura`
|
||||
(`docs\cercetare\rec_cale_vanzari_detalii.md:59-65`, coloanele `PRET`, `PRETD`, `ID_VALUTAD`,
|
||||
`ID_VALUTA` alaturi). Deci **da**, se pastreaza si urma valutei originale pe linie, dar valoarea
|
||||
de facturare efectiva e mereu in lei pe `VANZARI_DETALII.PRET`.
|
||||
|
||||
**La ce se foloseste `VANZARI_CURSURI`**: e un instantaneu al cursurilor pentru **orice valuta
|
||||
straina aparuta printre liniile documentului** (nu doar valuta proprie a documentului), scris o
|
||||
singura data la emitere, indiferent de `in_valuta`:
|
||||
```
|
||||
PACK_FACTURARE.sql:14491-14501
|
||||
PROCEDURE scrie_cursuri(V_ID_VANZARE IN NUMBER) IS
|
||||
BEGIN
|
||||
INSERT INTO VANZARI_CURSURI (ID_VANZARE, ID_VALUTA, CURS, MULTIPLICATOR)
|
||||
SELECT DISTINCT V_ID_VANZARE, ID_VALUTA, CURS, MULTIPLICATOR
|
||||
FROM VANZARI_DETALII_TEMP
|
||||
WHERE ID_VALUTA <> pack_facturare.nid_moneda_nationala;
|
||||
END scrie_cursuri;
|
||||
```
|
||||
Rulat necondiționat la fiecare emitere (apelat din `scrie_in_vanzari`, vezi
|
||||
`docs\cercetare\rec_cale_vanzari_detalii.md:98-102`) — deci **si pe o factura in lei** cu articole
|
||||
in valuta se scrie cate un rand `VANZARI_CURSURI` pentru fiecare valuta straina aparuta pe linii,
|
||||
cu cursul citit la `poDate.zi_curs`. Tabela e folosita ulterior la reafisare/reprint/retur, ca sursa
|
||||
a cursului per-linie (JOIN-urile de mai sus).
|
||||
|
||||
---
|
||||
|
||||
## 4. Ce se strica daca ascundem campul cand "nu are sens"
|
||||
|
||||
**Concluzie**: nu exista risc de "factura fara curs deloc" — `poDate.zi_curs` primeste mereu o
|
||||
valoare implicita la `Init` (data documentului) si nu poate ramane `NULL`. Riscul real e altul:
|
||||
**userul pierde controlul asupra datei de curs pentru cazul (b)** — o factura in lei cu articole in
|
||||
valuta ar folosi mereu cursul zilei curente/implicite, fara sa poata fi corectat manual, exact in
|
||||
situatia in care lipseste cursul pentru acea data (eroarea Oracle 20005, punctul 5) sau cand userul
|
||||
vrea sa aliniaze cursul cu data unui document sursa (aviz, contract).
|
||||
|
||||
**Consumatori confirmati ai `poDate.zi_curs`** (grep exhaustiv `poDate\.zi_curs`, fisiere
|
||||
`ofacturare.vc2`, `ofacturare.prg`, `ofacturare_stoc.prg` — singurele 3 din COMUN):
|
||||
|
||||
| Loc | Ce primeste | Conditionat de `in_valuta`? |
|
||||
|---|---|---|
|
||||
| `ofacturare.vc2:6105-6107`, `:13994-13996`, `:18030-18032` | parametru `to_date(...)` catre `pack_facturare.initializeaza_date_factura(...)` la fiecare finalizare de antet | **Nu** — trimis pentru orice tip |
|
||||
| `ofacturare.prg:272,276,281,297,303` | primul parametru al `pack_facturare.cursor_articole_k` / `cursor_preturi` / `cursor_gestiune` / `cursor_lucrare` — SQL-ul care aduce lista de articole/preturi afisata userului | **Nu** — inclusiv pentru `tip=1` (lista de preturi, lei) |
|
||||
| `ofacturare_stoc.prg:79,335` | acelasi rol, pe calea alternativa "facturare din stoc" | Nu |
|
||||
| `ofacturare.vc2:15097-15098`, `:19004-19005` | eticheta grilei "Curs valutar (data)" din `frm_facturare_articole2` | Nu — apare oricand `crscursuri` are randuri |
|
||||
| `ofacturare.vc2:9484` | validare "Nu ati completat ziua cursului valutar" | **Da**, doar `in_valuta=1` (`frm_date_factura`) |
|
||||
| `ofacturare.vc2:8076` | aceeasi validare | **Nu**, necondiționata (`frm_date_aviz_lucrare`) |
|
||||
|
||||
**Riscul concret**: daca regula noua ascunde/dezactiveaza campul strict cand `poDate.in_valuta=0`,
|
||||
pe `frm_date_factura` (tip 1, lista de preturi) userul nu va mai putea edita `zi_curs` inainte de a
|
||||
deschide grila de articole — dar `ofacturare.prg:279-282` tot va trimite acel `poDate.zi_curs`
|
||||
(neschimbat, ramas pe data initializata la `Init`) catre `cursor_preturi`, iar daca acolo Oracle
|
||||
ridica eroarea 20005 (curs lipsa pentru acea data/valuta), fluxul de recuperare
|
||||
(`vizualizeaza_curs`, punctul 5) va porni oricum, dar userul nu va (mai) avea camp pe antet ca sa
|
||||
retina/corecteze data dupa ce inchide formularul de curs. Pe `frm_date_aviz_lucrare`, ascunderea ar
|
||||
intra chiar in conflict cu validarea necondiționata de la `:8076`, care ar bloca finalizarea
|
||||
antetului cerand un camp care nu mai exista pe ecran — de reparat impreuna, nu doar ascuns.
|
||||
|
||||
---
|
||||
|
||||
## 5. Formularul de curs valutar din antet — localizare si traseu
|
||||
|
||||
**Concluzie**: nu exista niciun buton/dblclick pe `Clb_zi_curs` care sa deschida formularul de curs
|
||||
(verificat exhaustiv — zero hit pentru `Clb_zi_curs.DblClick/RightClick/Click` sau `but_curs` in
|
||||
`ofacturare.vc2`). Formularul se deschide **automat**, ca recuperare de eroare, dupa ce antetul
|
||||
(`frm_date_factura`/`frm_date_aviz`) s-a inchis deja si codul incearca sa incarce lista de articole.
|
||||
|
||||
**Traseu**:
|
||||
1. `ofacturare.prg:228-235` — `ofrmceredate = Createobject(lcObiect, toFactura)` (`lcObiect` =
|
||||
`frm_date_factura` sau `frm_date_aviz`), `.Show()` modal; la inchidere, `Release ofrmceredate`
|
||||
(`:248`).
|
||||
2. `ofacturare.prg:266-308` — pe baza tipului, se construieste apelul catre
|
||||
`pack_facturare.cursor_preturi(?poDate.zi_curs, ...)` (sau `cursor_articole_k`/`cursor_gestiune`/
|
||||
`cursor_lucrare`) si se executa (`:311` `goExecutor.oExecute(lcSqlCursor, lcCursor)`).
|
||||
3. Daca esueaza cu eroarea Oracle **20005** (curs lipsa pentru data/valuta ceruta):
|
||||
```
|
||||
ofacturare.prg:313-317 (identic la :828-832)
|
||||
If lnSucces < 0
|
||||
AMESSAGEBOX(goExecutor.oPrelucrareEroare(), 16, "Eroare")
|
||||
If goExecutor.nEroare = 20005
|
||||
vizualizeaza_curs(poDate.zi_curs)
|
||||
ENDIF
|
||||
```
|
||||
4. `vizualizeaza_curs(tdDataCurs)` — `COMUN\programe\oproceduri_curs.prg:8-42` — construieste
|
||||
cursorul `crscurs` si deschide `loFrmCurs = Createobject("frm_curs", tdDataCurs)` /
|
||||
`.Show(1)` (modal).
|
||||
5. Clasa `frm_curs` e definita in **`COMUN\clase\onom_curs.vc2:537`** (`DEFINE CLASS frm_curs AS
|
||||
_frmbase ...`), cu formulare-satelit pentru adaugare curs: `frm_curs_nou`
|
||||
(`onom_curs.vc2:1066`) si `frm_curs_nou_multiplu` (`onom_curs.vc2:1330`, apelat de la
|
||||
`onom_curs.vc2:941`).
|
||||
6. A doua cale catre acelasi formular: `citeste_cursuri_stoc` (`oproceduri_curs.prg:45-110`, folosit
|
||||
pe fluxul de facturare din stoc) cheama `vizualizeaza_curs()` **fara parametru de data**
|
||||
(`oproceduri_curs.prg:94`) cand gaseste valute fara curs pentru ziua ceruta, in bucla `Do While
|
||||
llVerificare` (retry pana userul completeaza sau renunta).
|
||||
|
||||
Aceasta e exact situatia din `COMUN\docs\todos.txt:45` (punctul 16): "la finalizare se verifica
|
||||
cursul valutar necesar pentru politicile de preturi care se factureaza [...] la revenire din
|
||||
formularul de curs valutar, focusul revine [...] pe TIP DOCUMENT, si la iesire din serie se
|
||||
regenereaza numar act" — confirmat ca fenomenul are loc **dupa** ce antetul (`frm_date_factura`) e
|
||||
deja inchis si eliberat (`Release ofrmceredate`, pasul 1), deci orice regenerare de numar/focus
|
||||
vizibila dupa inchiderea `frm_curs` tine de ecranul/starea care ramane activa in spate (nu s-a
|
||||
localizat mai departe — cere depanare separata, in afara scopului "doar localizare" cerut aici).
|
||||
|
||||
---
|
||||
|
||||
## Cand are sens campul „Data curs valutar" — propunere de regula
|
||||
|
||||
Campul are sens de aratat/editabil pe antet exact cand exista **vreo** sansa ca cursul zilei sa fie
|
||||
folosit la facturare — nu doar cand documentul insusi e in valuta:
|
||||
|
||||
> Arata (si activeaza) `Clb_zi_curs` cand `poDate.tip` NU e retur (`!Inlist(poDate.tip,8,9)`) **SI**
|
||||
> (`poDate.in_valuta = 1` **SAU** exista macar o politica de pret in valuta accesibila tipului
|
||||
> curent de document — adica exact conditia care astazi populeaza `crscursuri` cu randuri, verificata
|
||||
> deja empiric la `ofacturare.vc2:15092`/`:19000`: `Used('crscursuri') And Reccount('crscursuri') > 0`
|
||||
> dupa incarcarea listei de articole). Pe retur (8/9) ramane ascuns ca azi.
|
||||
|
||||
Pe `frm_date_aviz`/`frm_date_aviz_lucrare`, unde `crscursuri` nu e inca disponibil la momentul
|
||||
antetului (se incarca dupa, la fel ca la factura), regula echivalenta practicabila **pe antet** (nu
|
||||
dupa) ar fi: arata campul daca tipul documentului admite politici de pret in valuta pentru
|
||||
sucursala/gestiunea curenta (verificare care azi nu exista pe antet, doar mai tarziu pe grila de
|
||||
articole) — necesita fie mutarea verificarii mai devreme, fie acceptarea ca antetul nu poate sti cu
|
||||
certitudine inainte de a incarca articolele, caz in care campul ramane vizibil implicit si doar
|
||||
eticheta/relevanta lui se clarifica ulterior (ca azi, in `frm_facturare_articole2`).
|
||||
|
||||
---
|
||||
|
||||
## Necunoscute ramase
|
||||
|
||||
- Nu s-a confirmat daca exista si alte politici (`CRM_POLITICI_PRET*`) sau reguli de sucursala care
|
||||
determina *inainte* de deschiderea grilei de articole daca vor exista linii `tip_valuta=1` — utile
|
||||
pentru a decide vizibilitatea campului chiar pe antet, nu doar reactiv dupa incarcarea articolelor.
|
||||
- Nu s-a urmarit complet "focusul sare pe tip document / regenerare numar act" (punctul 5/todos #16)
|
||||
dupa inchiderea `frm_curs` — s-a localizat doar traseul de deschidere, nu si ecranul/handler-ul
|
||||
care ramane activ in spate si cauzeaza simptomul; cere sesiune separata de depanare (posibil in
|
||||
`poGeneratorNumere`/`clb_serie_act`, cf. `ofacturare.vc2:9735-9737`, needatate aici).
|
||||
- Layout-urile `.frx` (neconvertite) care afiseaza `poDate.Curs`/`cValuta` pe hartie nu au fost
|
||||
verificate — gap deja semnalat in `rec_consumatori_vanzari.md` (risc posibil #3), ramane valabil.
|
||||
- Nu s-a confirmat empiric (interogare Oracle) daca exista azi in productie facturi `tip=1` (lei) cu
|
||||
linii `ID_VALUTA <> moneda_nationala` in `VANZARI_DETALII` — dovada ar intari direct concluzia
|
||||
punctului 3, dar cercetarea a fost strict pe cod (fara conexiuni DB, conform mandatului).
|
||||
@@ -1,82 +1,101 @@
|
||||
# Capcană: corupere diacritice la editarea `.sc2`/`.vc2` (encoding cp1252)
|
||||
|
||||
Partajat între proiectele ROA* (similar cu `PROMPT_cautare_vfp.md` din acest folder) — capcana
|
||||
ține de formatul `.sc2`/`.vc2` produs de FoxBin2Prg, nu de un proiect anume.
|
||||
|
||||
Descoperit de 2 ori în aceeași sesiune (2026-07-10, în ROAAUTO): odată în
|
||||
`COMUN/clase/cmd_butoane.vc2` (clasa `cmd_select_adv`), odată în `Clase/ofundal_dev.vc2`
|
||||
(meniul principal) — de fiecare dată un agent anterior a editat text-cache-ul cu un tool care
|
||||
nu scrie cp1252 nativ, și a corupt TOATE caracterele cu diacritice din fișier, nu doar linia
|
||||
pe care voia s-o schimbe.
|
||||
|
||||
## De ce se întâmplă
|
||||
|
||||
Fișierele `.sc2`/`.vc2` generate de FoxBin2Prg sunt **cp1252 (Windows-1252)**, nu UTF-8
|
||||
(vezi antetul fiecărui fișier: `CPID="1252"`). Dacă un editor/tool citește fișierul ca UTF-8
|
||||
(sau alt encoding), fiecare byte >= 0x80 (diacritic) devine invalid ca secvență UTF-8 și e
|
||||
înlocuit cu caracterul de replacement U+FFFD. Dacă apoi tool-ul **salvează rezultatul tot ca
|
||||
UTF-8**, acel U+FFFD e scris ca 3 octeți UTF-8 (`0xEF 0xBF 0xBD`) — care, citiți înapoi ca
|
||||
cp1252 (cum face FoxBin2Prg la write-back), apar ca `�`. Rezultatul: caracterul original e
|
||||
**ireversibil pierdut** (nu mai există în fișier sub nicio formă) — recuperabil DOAR din altă
|
||||
sursă (git history, backup).
|
||||
|
||||
Codebase-ul ROA folosește un hack vechi de "reciclare" a unor caractere cp1252 needependente
|
||||
de Ș/ă/ț (care nu au echivalent direct în cp1252) pentru diacritice românești:
|
||||
|
||||
| Literă românească | Caracter folosit (cp1252) | Byte |
|
||||
|---|---|---|
|
||||
| ă | ã (a-tilde) | `0xE3` |
|
||||
| Ă | Ã | `0xC3` |
|
||||
| ț | þ (thorn minuscul) | `0xFE` |
|
||||
| Ș (majusculă) | ª (ordinal masculin) | `0xAA` |
|
||||
| ș (minusculă) | º (ordinal feminin) | `0xBA` |
|
||||
| î, â | î, â (existente nativ în cp1252) | `0xEE`, `0xE2` |
|
||||
|
||||
Aceste caractere par "gunoi"/typo la prima vedere într-un editor UTF-8 (`ã`, `þ`, `ª`, `º`) —
|
||||
**sunt corecte, nu le "corecta" fără să verifici encoding-ul.**
|
||||
|
||||
## Cum se verifică dacă un fișier `.sc2`/`.vc2` e corupt
|
||||
|
||||
```powershell
|
||||
$bytes = [System.IO.File]::ReadAllBytes("<path>.vc2")
|
||||
$text = [System.Text.Encoding]::GetEncoding(1252).GetString($bytes)
|
||||
$text -split "`r`n" | Select-String ([char]0xFFFD) # cauta caracterul de replacement
|
||||
```
|
||||
|
||||
Dacă apare `�` (sau `$text` conține U+FFFD) în output — fișierul are corupere de encoding.
|
||||
|
||||
## Cum se repară
|
||||
|
||||
1. **Nu edita orbește peste corupere** — caracterul original e deja pierdut din fișierul
|
||||
curent.
|
||||
2. Dacă fișierul e sub control de versiune (git) și corupera s-a întâmplat **într-o sesiune
|
||||
anterioară necomisă** (deci HEAD-ul git încă are versiunea curată): recuperează originalul
|
||||
convertind binarul din HEAD în text și comparând:
|
||||
```bash
|
||||
git show HEAD:<cale>.vcx > /tmp/head.vcx
|
||||
git show HEAD:<cale>.vct > /tmp/head.vct # (sau .VCT, dupa caz)
|
||||
powershell -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source /tmp/head.vcx -CacheRoot /tmp/head_out
|
||||
```
|
||||
apoi decodează ambele fișiere (HEAD curat + curent corupt) ca cp1252 și compară linie cu
|
||||
linie (PowerShell, nu `diff` direct — `diff`/Bash nu decodează cp1252 corect pentru afișare,
|
||||
deși detectează totuși diferența de octeți).
|
||||
3. Reconstruiește fișierul text pornind de la versiunea HEAD (curată), și reaplică DOAR
|
||||
modificările intenționate din sesiunea curentă peste ea (nu invers — nu încerca să "cârpești"
|
||||
fișierul corupt caracter cu caracter, e mai sigur să repornești de la baza curată).
|
||||
4. Scrie rezultatul înapoi ca bytes cp1252 (`[System.Text.Encoding]::GetEncoding(1252).GetBytes(...)`),
|
||||
NU ca string UTF-8/`Out-File` implicit (care scrie UTF-8 sau UTF-16 după caz).
|
||||
5. Rulează write-back (`txt2vcx.ps1 -Force`) și verifică fidelity check = zero diferențe.
|
||||
|
||||
## Cum se evită pe viitor
|
||||
|
||||
Când editezi `.sc2`/`.vc2` cu tool-uri text (Read/Edit/Write), verifică întâi dacă fișierul
|
||||
conține diacritice (`ã`, `þ`, `ª`, `º`, `î`, `â` etc.) — dacă da, **orice rescrie completă a
|
||||
fișierului trebuie făcută la nivel de octeți cu encoding cp1252 explicit**, nu presupunând
|
||||
UTF-8 implicit. Editările punctuale (Edit tool, string replace) sunt sigure DOAR dacă tool-ul
|
||||
păstrează restul fișierului byte-identic (nu rescrie tot fișierul reîncodat).
|
||||
|
||||
## Vezi și
|
||||
|
||||
`PROMPT_cautare_vfp.md` din acest folder, pasul 3.c — menționează deja riscul ("Headerul
|
||||
CPID="1252" poate minți...") pe scurt; acest fișier e detalierea completă (tabel de caractere,
|
||||
pași de recuperare din git).
|
||||
# Capcană: corupere diacritice la editarea `.sc2`/`.vc2`
|
||||
|
||||
Partajat între proiectele ROA* — capcana ține de formatul `.sc2`/`.vc2` produs de FoxBin2Prg,
|
||||
nu de un proiect anume.
|
||||
|
||||
## De ce se întâmplă
|
||||
|
||||
Fișierele `.sc2`/`.vc2` sunt **cp1250** (Windows-1250, Europa Centrală), nu UTF-8 — deși
|
||||
antetul FoxBin2Prg declară `CPID="1252"`. Eticheta din antet nu corespunde conținutului:
|
||||
controalele care poartă text cu diacritice au `FontCharSet = 238` (Europa de Est), adică VFP
|
||||
le randează tot ca cp1250. Diferența nu e cosmetică — un `ă` real scris prin cp1252 nu are
|
||||
echivalent în acel codepage și s-ar pierde; scris prin cp1250 (encoding-ul real al fișierului)
|
||||
e pur și simplu octetul `0xE3`, corect și stabil.
|
||||
|
||||
Dacă un editor/tool citește fișierul ca UTF-8, fiecare byte >= 0x80 (diacritic) devine invalid
|
||||
ca secvență UTF-8 și e înlocuit cu U+FFFD. Dacă tool-ul apoi **salvează tot ca UTF-8**, acel
|
||||
U+FFFD e scris ca 3 octeți (`0xEF 0xBF 0xBD`) — care, citiți înapoi ca cp1250 (cum face
|
||||
FoxBin2Prg la write-back), apar ca `�`. Caracterul original e **ireversibil pierdut**
|
||||
(recuperabil DOAR din altă sursă: git history, backup).
|
||||
|
||||
Octeții diacriticelor din codebase-ul ROA, cu adevărul (cp1250) și aparența dacă îi decodezi
|
||||
greșit ca cp1252:
|
||||
|
||||
| Literă românească | Byte | Aparență dacă decodezi ca cp1252 |
|
||||
|---|---|---|
|
||||
| ă | `0xE3` | ã (a-tilde) |
|
||||
| Ă | `0xC3` | Ã |
|
||||
| î | `0xEE` | î (identic — zonă comună cp1250/cp1252) |
|
||||
| Î | `0xCE` | Î (identic — zonă comună cp1250/cp1252) |
|
||||
| â | `0xE2` | â (identic — zonă comună cp1250/cp1252) |
|
||||
| ț | `0xFE` | þ (thorn minuscul) |
|
||||
| Ș (majusculă) | `0xAA` | ª (ordinal masculin) |
|
||||
| ș (minusculă) | `0xBA` | º (ordinal feminin) |
|
||||
|
||||
Decodate cp1250 (encoding-ul real), aceste litere sunt diacritice românești normale — exact
|
||||
ce apare în formular când fișierul e sănătos. Par "gunoi"/typo (`ã`, `þ`, `ª`, `º`) **doar
|
||||
dacă le decodezi cu codepage-ul greșit** — nu le "corecta" fără să verifici encoding-ul real.
|
||||
|
||||
## Cum se verifică dacă un fișier `.sc2`/`.vc2` e corupt
|
||||
|
||||
Verificarea se face **pe octeți**, nu pe text decodat: un codepage single-byte (1250 sau 1252)
|
||||
mapează fiecare octet la un caracter, deci nu produce niciodată U+FFFD — o căutare de
|
||||
`[char]0xFFFD` în textul decodat nu găsește nimic nici pe un fișier stricat. Ce se caută e
|
||||
secvența de trei octeți pe care a lăsat-o tool-ul care a stricat fișierul:
|
||||
|
||||
```powershell
|
||||
$b = [System.IO.File]::ReadAllBytes("<path>.vc2")
|
||||
$n = 0
|
||||
for ($i = 0; $i -lt $b.Length - 2; $i++) {
|
||||
if ($b[$i] -eq 0xEF -and $b[$i+1] -eq 0xBF -and $b[$i+2] -eq 0xBD) { $n++; $i += 2 }
|
||||
}
|
||||
"EF BF BD (U+FFFD) x $n" # orice valoare > 0 = fisier stricat
|
||||
```
|
||||
|
||||
Echivalentul din Bash, util și pentru censul complet înainte/după orice editare (vezi
|
||||
`reguli_lucru.md`, punctul 7):
|
||||
|
||||
```bash
|
||||
od -An -tx1 <path>.vc2 | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c
|
||||
```
|
||||
|
||||
Censul **crește** la stricare — un octet cp1250 devine trei octeți de U+FFFD — deci nu urmări
|
||||
doar scăderile. Decodat cp1250, `EF BF BD` apare ca `ďż˝` în caption.
|
||||
|
||||
## Cum se repară
|
||||
|
||||
1. **Nu edita orbește peste corupere** — caracterul original e deja pierdut din fișierul curent.
|
||||
2. Dacă corupera s-a întâmplat într-o sesiune anterioară necomisă (HEAD-ul git încă e curat):
|
||||
recuperează originalul convertind binarul din HEAD în text:
|
||||
```bash
|
||||
git show HEAD:<cale>.vcx > /tmp/head.vcx
|
||||
git show HEAD:<cale>.vct > /tmp/head.vct # (sau .VCT, dupa caz)
|
||||
powershell -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source /tmp/head.vcx -CacheRoot /tmp/head_out
|
||||
```
|
||||
Dacă și HEAD e deja corupt (corupera a fost comisă), caută ultima versiune curată cu
|
||||
`git cat-file blob <commit>:<cale>` (din Bash, niciodată cu `>` din PowerShell 5.1 — adaugă
|
||||
BOM și re-encodează) sau `svn cat <fișier>` — ambele surse independente de encoding-ul
|
||||
curent al fișierului.
|
||||
Apoi decodează ambele fișiere (versiunea curată + curent corupt) ca cp1250 și compară linie
|
||||
cu linie (PowerShell, nu `diff`/Bash direct — nu decodează cp1250 corect la afișare, deși
|
||||
detectează totuși diferența de octeți).
|
||||
3. Reconstruiește fișierul text pornind de la versiunea curată, reaplicând DOAR modificările
|
||||
intenționate din sesiunea curentă (nu invers — nu cârpi fișierul corupt caracter cu
|
||||
caracter).
|
||||
4. Scrie rezultatul înapoi ca bytes cp1250
|
||||
(`[System.Text.Encoding]::GetEncoding(1250).GetBytes(...)`), NU ca string UTF-8/`Out-File`
|
||||
implicit.
|
||||
5. Rulează write-back (`txt2vcx.ps1 -Force`) și verifică fidelity check = zero diferențe.
|
||||
|
||||
## Cum se evită pe viitor
|
||||
|
||||
Când editezi `.sc2`/`.vc2` cu tool-uri text (Read/Edit/Write), verifică întâi dacă fișierul
|
||||
conține diacritice (`ă`, `ț`, `Ș`, `ș`, `î`, `â` etc.) — dacă da, **orice rescrie completă
|
||||
trebuie făcută la nivel de octeți cu encoding cp1250 explicit**, nu presupunând UTF-8.
|
||||
Editările punctuale (Edit tool, string replace) sunt sigure DOAR dacă tool-ul păstrează restul
|
||||
fișierului byte-identic (nu rescrie tot fișierul reîncodat).
|
||||
|
||||
## Vezi și
|
||||
|
||||
`PROMPT_cautare_vfp.md` din acest folder, pasul 3.c — menționează riscul pe scurt; acest fișier
|
||||
e detalierea completă (tabel de caractere, pași de recuperare din git).
|
||||
|
||||
@@ -1,65 +1,55 @@
|
||||
# Capcană: `ALTER TABLE` pe cursorul întors de `goExecutor.oExecute()`
|
||||
|
||||
Partajat între proiectele ROA* — `goExecutor` (clasa `oExecutor`, definită în
|
||||
`COMUN/programe/oproceduri_comune.prg`, metoda `oExecute`) e utilitarul standard pentru
|
||||
interogări SQL pass-through (`SQLExec`) către Oracle, folosit peste tot în codul ROA*.
|
||||
|
||||
## Ce nu funcționează
|
||||
|
||||
```foxpro
|
||||
lnSucces = goExecutor.oExecute(lcSql, lcCursor)
|
||||
...
|
||||
ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pică
|
||||
```
|
||||
|
||||
Cursorul întors de `oExecute()` (rezultatul unui `SQLExec`) poate refuza comenzi DDL
|
||||
ulterioare, cu erori în lanț (descoperite empiric, în această ordine, în ROAAUTO
|
||||
`autopass_cursor_comenzi`/`autopass_cursor_operatii`):
|
||||
|
||||
1. `Function is not supported on remote tables.` — pe `ALTER TABLE` direct pe cursorul
|
||||
original.
|
||||
2. Chiar și după o încercare de rematerializare (`SELECT * FROM (cursor) INTO CURSOR
|
||||
(acelasi_nume) READWRITE`) → `Alias name is already in use.` (sursa și ținta nu pot
|
||||
avea același nume într-un `SELECT...INTO CURSOR`).
|
||||
3. Cu un alias scratch diferit ca țintă (`SELECT * FROM (cursor) INTO CURSOR
|
||||
(nume_final_diferit_de_sursa) READWRITE`) → tot `Invalid operation for the cursor.` pe
|
||||
`ALTER TABLE`, chiar dacă acum cursorul final teoretic ar trebui să fie unul local
|
||||
obișnuit.
|
||||
|
||||
Nu există niciun alt loc în codul ROA* care să facă `ALTER TABLE` imediat după
|
||||
`goExecutor.oExecute()` — deci acest pattern nu avea niciun precedent testat înainte de
|
||||
funcțiile AUTOPASS.
|
||||
|
||||
## Ce funcționează
|
||||
|
||||
**Nu folosi `ALTER TABLE` deloc pe rezultatul unui `oExecute()`.** Include coloanele
|
||||
suplimentare direct în `SELECT`-ul de rematerializare, ca expresii literale alături de `*`
|
||||
(VFP suportă `SELECT *, expr AS coloana FROM ...`):
|
||||
|
||||
```foxpro
|
||||
lcCursorRaw = lcCursor + '_raw'
|
||||
IF USED(lcCursorRaw)
|
||||
USE IN (lcCursorRaw)
|
||||
ENDIF
|
||||
|
||||
lnSucces = goExecutor.oExecute(lcSql, lcCursorRaw)
|
||||
IF lnSucces < 0
|
||||
* tratare eroare, RETURN
|
||||
ENDIF
|
||||
|
||||
SELECT *, .F. AS coloananoua, SPACE(100) AS altacoloana ;
|
||||
FROM (lcCursorRaw) INTO CURSOR (lcCursor) READWRITE
|
||||
USE IN (lcCursorRaw)
|
||||
|
||||
* de-aici incolo doar REPLACE (date), NICIODATA ALTER TABLE (structura) pe (lcCursor)
|
||||
```
|
||||
|
||||
După acest pas, cursorul (`lcCursor`) e un cursor local obișnuit — `ALTER TABLE` funcționează
|
||||
normal pe el DUPĂ ACEEA (ex. dintr-o altă funcție care primește cursorul deja gata construit,
|
||||
nu direct rezultatul unui `oExecute`), doar comanda imediat următoare unui `oExecute()` e
|
||||
restricționată.
|
||||
|
||||
## Vezi și
|
||||
|
||||
Exemplu complet aplicat: ROAAUTO, `Programe/oproceduri_autopass.prg`,
|
||||
`autopass_cursor_comenzi()`/`autopass_cursor_operatii()`.
|
||||
# Capcană: `ALTER TABLE` pe cursorul întors de `goExecutor.oExecute()`
|
||||
|
||||
Partajat între proiectele ROA* — `goExecutor` (clasa `oExecutor`, definită în
|
||||
`COMUN/programe/oproceduri_comune.prg`, metoda `oExecute`) e utilitarul standard pentru
|
||||
interogări SQL pass-through (`SQLExec`) către Oracle, folosit peste tot în codul ROA*.
|
||||
|
||||
## Ce nu funcționează
|
||||
|
||||
```foxpro
|
||||
lnSucces = goExecutor.oExecute(lcSql, lcCursor)
|
||||
...
|
||||
ALTER TABLE (lcCursor) ADD COLUMN coloananoua L && <- pică
|
||||
```
|
||||
|
||||
Cursorul întors de `oExecute()` poate refuza comenzi DDL ulterioare, cu erori în lanț
|
||||
(descoperite empiric, în această ordine):
|
||||
|
||||
1. `Function is not supported on remote tables.` — pe `ALTER TABLE` direct pe cursorul original.
|
||||
2. Chiar și după rematerializare (`SELECT * FROM (cursor) INTO CURSOR (acelasi_nume) READWRITE`)
|
||||
→ `Alias name is already in use.` (sursa și ținta nu pot avea același nume).
|
||||
3. Cu alias scratch diferit ca țintă → tot `Invalid operation for the cursor.` pe `ALTER TABLE`,
|
||||
chiar dacă țintă ar trebui să fie deja un cursor local obișnuit.
|
||||
|
||||
## Ce funcționează
|
||||
|
||||
**Nu folosi `ALTER TABLE` deloc pe rezultatul unui `oExecute()`.** Include coloanele
|
||||
suplimentare direct în `SELECT`-ul de rematerializare, ca expresii literale alături de `*`
|
||||
(VFP suportă `SELECT *, expr AS coloana FROM ...`):
|
||||
|
||||
```foxpro
|
||||
lcCursorRaw = lcCursor + '_raw'
|
||||
IF USED(lcCursorRaw)
|
||||
USE IN (lcCursorRaw)
|
||||
ENDIF
|
||||
|
||||
lnSucces = goExecutor.oExecute(lcSql, lcCursorRaw)
|
||||
IF lnSucces < 0
|
||||
* tratare eroare, RETURN
|
||||
ENDIF
|
||||
|
||||
SELECT *, .F. AS coloananoua, SPACE(100) AS altacoloana ;
|
||||
FROM (lcCursorRaw) INTO CURSOR (lcCursor) READWRITE
|
||||
USE IN (lcCursorRaw)
|
||||
|
||||
* de-aici incolo doar REPLACE (date), NICIODATA ALTER TABLE (structura) pe (lcCursor)
|
||||
```
|
||||
|
||||
După acest pas, cursorul (`lcCursor`) e un cursor local obișnuit — `ALTER TABLE` funcționează
|
||||
normal pe el DUPĂ ACEEA (ex. într-o altă funcție care primește cursorul deja gata construit),
|
||||
doar comanda imediat următoare unui `oExecute()` e restricționată.
|
||||
|
||||
## Vezi și
|
||||
|
||||
Exemplu complet aplicat: ROAAUTO, `Programe/oproceduri_autopass.prg`,
|
||||
`autopass_cursor_comenzi()`/`autopass_cursor_operatii()`.
|
||||
|
||||
21
docs/conventie_null_vfp.md
Normal file
21
docs/conventie_null_vfp.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Garzi pe valori NULL (VFP)
|
||||
|
||||
Campurile din cursoarele intoarse de Oracle pot fi `.NULL.`. In VFP `EMPTY(.NULL.)` intoarce
|
||||
`.F.`, deci o garda scrisa doar cu `EMPTY()` **nu prinde NULL**, iar concatenarea cu NULL face
|
||||
tot sirul NULL (inclusiv un SQL construit prin `+`).
|
||||
|
||||
Forma corecta, cu tipul evaluat primul ca sa opreasca acolo:
|
||||
|
||||
```foxpro
|
||||
If Type('tcCont') # 'C' Or Empty(Nvl(tcCont, ''))
|
||||
Return
|
||||
Endif
|
||||
```
|
||||
|
||||
- `Nvl(x, '')` in interiorul lui `Empty()`, nu `Isnull(x) Or Empty(x)`.
|
||||
- `TYPE()` pe o variabila cu NULL de tip caracter intoarce tot `'C'` - nu tine loc de `Nvl`.
|
||||
- Acelasi tratament la orice text construit prin `+` din campuri de cursor
|
||||
(SQL, mesaje, chei): un singur camp NULL anuleaza tot sirul.
|
||||
|
||||
Simptom tipic cand lipseste garda: `SQL statement parameter is required for non-prepared
|
||||
SQLEXEC() calls` in `OEXECUTOR.OEXECUTE` - SQL-ul ajuns la `SQLEXEC` era `.NULL.`.
|
||||
@@ -1,64 +1,53 @@
|
||||
# Convenție UX pentru formulare VFP (preferința lui Marius, valabilă pe toate proiectele ROA*)
|
||||
|
||||
Partajat între proiectele ROA* (similar cu `PROMPT_cautare_vfp.md`, `prompt_project_insights_docs.md`
|
||||
din acest folder) — pentru că `COMUN\` e clonat/sincronizat în fiecare aplicație ROA, e locul
|
||||
corect pentru o convenție de design care nu ține de un singur proiect.
|
||||
|
||||
Origine: confirmat de Marius pe `frm_autopass.scx` (ROAAUTO) după o rundă de regrupare vizuală
|
||||
(2026-07-10) — "imi place designul acesta" pe layout-ul cu rânduri clar separate pe funcție,
|
||||
butoane grupate la margini, fără elemente lipite unele de altele.
|
||||
|
||||
## Ce înseamnă in practică, pe proprietăți VFP
|
||||
|
||||
- **Fiecare grup funcțional pe rândul lui** — nu înghesui controale fără legătură directă pe
|
||||
același `Top`. Ex: rândul de perioadă (date + Actualizează) separat de rândul de
|
||||
statistici (Declarabile/Transmise/Blocate), separat de panoul de configurare.
|
||||
- **Spațiere vizibilă între grupuri, strânsă în interiorul unui grup** — butoane din
|
||||
aceeași acțiune (ex. Validează dry-run → Transmite → Renunță) la 6-10px unele de altele;
|
||||
gap de 20-30px față de următorul grup funcțional (ex. Selectează tot vs. grupul
|
||||
Validare/Transmitere vs. Actualizează statusuri).
|
||||
- **Butoanele secundare/de configurare aliniate la marginea din dreapta a containerului**,
|
||||
nu lipite imediat după textbox-ul pe care îl controlează — altfel nu se disting vizual ca
|
||||
acțiune separată de câmpul de input.
|
||||
- **Acțiunea principală + oprirea ei alăturate** — un buton de tip "Renunță/Oprește" trebuie
|
||||
poziționat lângă acțiunea pe care o anulează (ex. Transmite + Renunță), nu împrăștiat în
|
||||
altă parte a rândului.
|
||||
- **Un singur rând de acțiuni cât se poate** — dacă mai multe grupuri de butoane încap pe
|
||||
lățimea formei, preferă un singur rând orizontal în loc să adaugi rânduri noi dedesubt;
|
||||
păstrează formele compacte pe verticală.
|
||||
- **Caption-uri scurte, sentence case, nu ALL CAPS** — ex. "Transmite" nu "TRANSMITE";
|
||||
"Dashboard AutoPass" nu "Deschide dashboard AUTOPASS". ALL CAPS/text lung pe un buton
|
||||
citește ca zgomot, nu ca ierarhie.
|
||||
- **Culoare = semnal, nu decor** — folosește culoare distinctă doar pentru acțiuni cu
|
||||
semnificație clară (verde = acțiune pozitivă/transmite, roșu = oprire/pericol, albastru =
|
||||
navigare/deschidere link extern); restul butoanelor rămân stilul implicit din `_baza.vcx`.
|
||||
|
||||
## Clase de controale (confirmat de Marius, 24.07.2026, pe frm_verif_partener_anaf ROACONT)
|
||||
|
||||
- **Intotdeauna controale din `_baza.vcx`, nu controale native VFP** — orice grid, label,
|
||||
textbox, checkbox etc. dintr-un formular nou se bazeaza pe clasa corespunzatoare din
|
||||
`COMUN\clase\_baza.vcx`, nu pe clasa nativa Visual FoxPro. Clasele din `_baza.vcx` au
|
||||
fontul default **Arial 10** — nu se suprascrie FontName pe controale (explicit: fara
|
||||
Arial Narrow).
|
||||
- **Butoanele de inchidere/confirmare stau in bara de titlu**, din `cmd_butoane.vcx` —
|
||||
modelul Renunt/Termin (clasa de forma `frm_termin_renunt` din `_frm_child.vcx` le aduce
|
||||
deja). Nu se dubleaza aceste actiuni cu butoane in corpul formei.
|
||||
- **Actiunile care au corespondent `but_*` in `cmd_butoane.vcx`** (Nou/Adauga, Modifica,
|
||||
Salveaza, Sterge, Verifica etc.) folosesc CU PREDILECTIE clasa dedicata `but_*`
|
||||
respectiva — nu se improvizeaza un buton generic pentru o actiune care are deja clasa ei.
|
||||
- **Doar actiunile FARA corespondent `but_*`** primesc butoane pe clasele `cmd_*` din
|
||||
`cmd_butoane.vcx` (ex. `cmd_executa`) — nu clase improvizate si nu CommandButton nativ.
|
||||
|
||||
## Vocabular
|
||||
|
||||
Funcțional, compact, aerisit, minimalist, grupat, ușor de înțeles de utilizatori, aer aerisit,
|
||||
modern — asta e reperul calitativ pentru orice formular nou sau refacere de layout, dincolo de
|
||||
regulile mecanice de mai sus, pe orice aplicație ROA*.
|
||||
|
||||
## Vezi și
|
||||
|
||||
- `PROMPT_cautare_vfp.md` din acest folder — cum se caută/editează cod în binarele VFP text-cache
|
||||
(relevant când aplici aceste reguli prin fluxul `.sc2`/`.vc2` + write-back).
|
||||
- `conventie_encoding_cp1252.md` din acest folder — capcana de corupere a diacriticelor la
|
||||
editarea `.sc2`/`.vc2`; relevantă ori de câte ori editezi text-cache-ul unui formular/librărie
|
||||
pentru a aplica aceste reguli de UX.
|
||||
# Convenție UX pentru formulare VFP (preferința lui Marius, valabilă pe toate proiectele ROA*)
|
||||
|
||||
Partajat între proiectele ROA* — `COMUN\` e clonat/sincronizat în fiecare aplicație ROA, e locul
|
||||
corect pentru o convenție de design care nu ține de un singur proiect.
|
||||
|
||||
## Ce înseamnă in practică, pe proprietăți VFP
|
||||
|
||||
- **Fiecare grup funcțional pe rândul lui**, nu înghesuit pe același `Top` cu altul fără
|
||||
legătură (ex: perioadă / statistici / configurare, pe rânduri separate).
|
||||
- **Spațiere vizibilă între grupuri, strânsă în interiorul unui grup** — butoane din aceeași
|
||||
acțiune la 6-10px unele de altele; gap de 20-30px față de următorul grup funcțional.
|
||||
- **Butoanele secundare/de configurare aliniate la marginea din dreapta a containerului**, nu
|
||||
lipite imediat după textbox-ul pe care îl controlează — altfel nu se disting ca acțiune
|
||||
separată de câmpul de input.
|
||||
- **Acțiunea principală + oprirea ei alăturate** (ex. Transmite + Renunță), nu împrăștiate în
|
||||
altă parte a rândului.
|
||||
- **Un singur rând de acțiuni cât se poate** — un rând orizontal in loc de rânduri noi
|
||||
dedesubt; formele rămân compacte pe verticală.
|
||||
- **Caption-uri scurte, sentence case, nu ALL CAPS** — ex. "Transmite" nu "TRANSMITE". ALL
|
||||
CAPS/text lung pe un buton citește ca zgomot, nu ca ierarhie.
|
||||
- **Culoare = semnal, nu decor** — doar pentru acțiuni cu semnificație clară (verde =
|
||||
pozitiv/transmite, roșu = oprire/pericol, albastru = navigare/link extern); restul butoanelor
|
||||
rămân stilul implicit din `_baza.vcx`.
|
||||
|
||||
## Clase de controale (confirmat de Marius, 24.07.2026, pe frm_verif_partener_anaf ROACONT)
|
||||
|
||||
- **Intotdeauna controale din `_baza.vcx`, nu controale native VFP** — orice grid, label,
|
||||
textbox, checkbox etc. dintr-un formular nou se bazeaza pe clasa corespunzatoare din
|
||||
`COMUN\clase\_baza.vcx`, nu pe clasa nativa Visual FoxPro. Clasele din `_baza.vcx` au
|
||||
fontul default **Arial 10** — nu se suprascrie FontName pe controale (explicit: fara
|
||||
Arial Narrow).
|
||||
- **Butoanele de inchidere/confirmare stau in bara de titlu**, din `cmd_butoane.vcx` —
|
||||
modelul Renunt/Termin (clasa de forma `frm_termin_renunt` din `_frm_child.vcx` le aduce
|
||||
deja). Nu se dubleaza aceste actiuni cu butoane in corpul formei.
|
||||
- **Actiunile care au corespondent `but_*` in `cmd_butoane.vcx`** (Nou/Adauga, Modifica,
|
||||
Salveaza, Sterge, Verifica etc.) folosesc CU PREDILECTIE clasa dedicata `but_*`
|
||||
respectiva — nu se improvizeaza un buton generic pentru o actiune care are deja clasa ei.
|
||||
- **Doar actiunile FARA corespondent `but_*`** primesc butoane pe clasele `cmd_*` din
|
||||
`cmd_butoane.vcx` (ex. `cmd_executa`) — nu clase improvizate si nu CommandButton nativ.
|
||||
|
||||
## Vocabular
|
||||
|
||||
Funcțional, compact, aerisit, minimalist, grupat, ușor de înțeles de utilizatori, modern —
|
||||
asta e reperul calitativ pentru orice formular nou sau refacere de layout, pe orice
|
||||
aplicație ROA*.
|
||||
|
||||
## Vezi și
|
||||
|
||||
- `PROMPT_cautare_vfp.md` din acest folder — cum se caută/editează cod în binarele VFP text-cache
|
||||
(relevant când aplici aceste reguli prin fluxul `.sc2`/`.vc2` + write-back).
|
||||
- `conventie_encoding_cp1252.md` din acest folder — capcana de corupere a diacriticelor la
|
||||
editarea `.sc2`/`.vc2`; relevantă ori de câte ori editezi text-cache-ul unui formular/librărie
|
||||
pentru a aplica aceste reguli de UX.
|
||||
|
||||
176
docs/depanare-pack-update.md
Normal file
176
docs/depanare-pack-update.md
Normal file
@@ -0,0 +1,176 @@
|
||||
# Depanare actualizare ROA (CONTAFIN_ORACLE.PACK_UPDATE)
|
||||
|
||||
Actualizarea automata a aplicatiilor si a bazei ruleaza din jobul `CONTAFIN_ORACLE.UPDATEROA_ZILNIC`
|
||||
-> `PACK_UPDATE.UpdateROA`, in 3 etape secventiale: **UpdateApp** (descarca arhivele programelor) ->
|
||||
**UpdateScripts** (umple `UPD_DATABASE`) -> **UpdateDatabaseSqlPlus** (aplica scripturile pe scheme).
|
||||
O etapa esuata le opreste pe toate urmatoarele.
|
||||
|
||||
## Scriptul de diagnostic
|
||||
|
||||
`COMUN\utile\diag_actualizare.ps1 -Alias <ALIAS_TNS>` ruleaza tot lantul de mai jos si scoate un
|
||||
verdict (unde a ramas rularea, care e scriptul candidat, unde e eroarea). Strict read-only; `-Disc`
|
||||
adauga verificarea spatiului pe discurile serverului (singura parte care scrie ceva — un `.ps1`
|
||||
temporar in `DMPDIR`). Foloseste-l intai; sectiunile de mai jos explica ce citeste si de ce.
|
||||
|
||||
Cand cauza e spatiul (tablespace plin, audit/loguri Oracle care umplu discul), continua cu
|
||||
`depanare-spatiu-oracle.md` si `COMUN\utile\diag_spatiu.ps1`.
|
||||
|
||||
## Unde te uiti, in ordine
|
||||
|
||||
| Ce | Unde |
|
||||
|---|---|
|
||||
| pana unde a ajuns fiecare rulare | `UPD_ISTORIC` (`stare`: 0=start, 1=aplicatii, 2=scripturi, 3=aplicare, 4=incheiat; `dataora_end` gol = neincheiata) |
|
||||
| cauza reala a esecului | `UPD_LOG` (`dataora_start` = rularea, `secventa`+`dataora` = ordinea; `explicatie` e CLOB) |
|
||||
| ce a raportat jobul | `dba_scheduler_job_run_details` (`log_date`, `status`, `additional_info`) |
|
||||
| ce versiuni s-au descarcat | `UPD_PROGRAME` |
|
||||
| scripturi disponibile / aplicate | `UPD_DATABASE.script_date` vs `<schema>.VERSIUNE.data_script` |
|
||||
| **erorile din aplicarea scripturilor** | **`C:\DMPDIR\script_master.log` pe serverul de baze de date** |
|
||||
|
||||
Un sir de rulari oprite la aceeasi `stare` da direct etapa vinovata, iar prima zi din sir da data de
|
||||
la care s-a schimbat ceva.
|
||||
|
||||
## Capcane
|
||||
|
||||
- **`UPD_LOG` se goleste la fiecare rulare.** Nu ai istoric: iei log-ul rularii curente, altfel
|
||||
relansezi ca sa-l reproduci.
|
||||
- **Eroarea din `additional_info` a jobului e de obicei falsa.** Pe orice esec se apeleaza `EmailLog`,
|
||||
iar daca SMTP-ul e picat ridica `ORA-20000` care inlocuieste eroarea originala. Cauza adevarata e
|
||||
in `UPD_LOG`.
|
||||
- **`UpdateApp` abandoneaza tot la primul program nedescarcat** (`exit` din bucla, `CT_INSUCCES`) —
|
||||
deci si programele de dupa el in lista, si ambele etape de baza de date. Un singur fisier
|
||||
indisponibil blocheaza actualizarile la infinit, tacut.
|
||||
- **`GetStare` refuza o rulare noua** cat timp precedenta e neincheiata si nu a trecut o ora.
|
||||
Se deblocheaza cu `exec contafin_oracle.pack_update.IncheiereActualizare`.
|
||||
- Programele `%USERREPORTS%` merg toate in directorul `UPD_USERREPORTS`, nu in `UPD_<nume_program>`.
|
||||
|
||||
## Aplicarea scripturilor (script_master.log)
|
||||
|
||||
Etapa 3 nu ruleaza scripturile din PL/SQL, ci genereaza in `DMPDIR` (`C:\DMPDIR`) cate un
|
||||
`script_<SCHEMA>.sql` plus `script_master.sql`, pe care le da unui **SQL\*Plus extern**, cu iesirea
|
||||
in `C:\DMPDIR\script_master.log` (`script_master2.log` = pasii de la final).
|
||||
|
||||
**Erorile de aici NU ajung in `UPD_LOG`.** O rulare care esueaza la un script arata perfect curata
|
||||
in baza: `UPD_LOG` fara nicio eroare, doar `UpdateSchemaSQLPLUS ... / UpdateDatabaseSQLPLUS END`.
|
||||
Semnele indirecte sunt ca rularea ramane la `stare = 3` fara `dataora_end`, iar
|
||||
`<schema>.VERSIUNE` nu mai avanseaza. Scriptul vinovat e primul din `UPD_DATABASE` de dupa ultima
|
||||
versiune inregistrata acolo, iar mesajul real e doar in `script_master.log`.
|
||||
|
||||
Scripturile au `WHENEVER SQLERROR EXIT SQL.SQLCODE ROLLBACK`, deci primul esec opreste tot lantul
|
||||
si se repeta identic la fiecare rulare pana e reparat.
|
||||
|
||||
Fisierul se poate citi si fara acces la desktopul serverului, prin `UTL_FILE` pe directorul
|
||||
`DMPDIR` (`fopen(...,'R',32767)` + `get_line` in bucla; tine ultimele N linii intr-un tablou —
|
||||
partea utila e la sfarsit).
|
||||
|
||||
### Caz: nu orice esec de script e o problema de SQL (SIGMA, 03.08.2026)
|
||||
|
||||
`ff_2026_07_29_02_COMUN_TVA11.SQL` a picat pe `MARCU` cu `ORA-01653: unable to extend table
|
||||
SYS.INFO ... in tablespace SYSTEM` (din `SYS.PINFO`/`SYS.AUTH_PACK`, recursiv). Tablespace-ul
|
||||
`SYSTEM` era plin: autoextensibil, dar cu `maxbytes` atins la 600 MB, ~2 MB liberi. **Orice**
|
||||
script ar fi picat identic — `AUTH_PACK` scrie in `SYS.INFO` la fiecare conectare. Cand eroarea nu
|
||||
priveste obiectele scriptului, verifica intai spatiul.
|
||||
|
||||
Ce a contat, pentru data viitoare:
|
||||
|
||||
- **`maxbytes` mic nu e o limita XE.** Cele 11 GB ale XE sunt pe *date utilizator*; un plafon mic pe
|
||||
`SYSTEM.DBF` e o setare de instalare. Se ridica din `contafin_oracle` (are `ALTER DATABASE`):
|
||||
`alter database datafile '<cale>\SYSTEM.DBF' autoextend on next 50M maxsize 2000M;`
|
||||
- **Spatiul pe discul serverului se verifica fara RDP**, cu `sys.ExecuteScriptOS` (vezi mai jos) —
|
||||
`Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3"`, iesire in `DMPDIR`, citita cu `UTL_FILE`.
|
||||
Job asincron, dar raspunde in cateva secunde.
|
||||
- **`SYS.INFO` e tabel ROA, nu obiect de dictionar** (log de login scris de `PINFO`, ~7 randuri per
|
||||
conectare, +16-17k randuri/luna, nimic din baza nu-l citeste). Se poate goli, **dar numai ca
|
||||
`SYSDBA`**: privilegiile `ANY` (`DROP ANY TABLE`, `DELETE ANY TABLE`) nu se aplica pe obiectele
|
||||
din schema `SYS` cat timp `O7_DICTIONARY_ACCESSIBILITY=FALSE`, deci din `contafin_oracle` iese
|
||||
`ORA-01031`.
|
||||
- Restul lui `SYSTEM` era dictionar Oracle (`IDL_UB1$`, `SOURCE$`, `IDL_UB2$`, `ARGUMENT$` ~207 MB) —
|
||||
de neatins fara export/import. `AUD$`/`FGA_LOG$` erau goale. Recyclebin-ul si bloat-ul de scheduler
|
||||
stateau in `ROA`/`SYSAUX`, nu in `SYSTEM`.
|
||||
|
||||
## Descarcarea (UpdateApp)
|
||||
|
||||
Cu `server_info.POWERSHELLDOWNLOAD = '1'`, `PACK_UTILS.DownloadFileOS` scrie un `.ps1` cu `curl` in
|
||||
`DMPDIR`, il lanseaza cu `sys.ExecuteScriptOS` si asteapta aparitia fisierului in directorul Oracle
|
||||
`UPD_<PROGRAM>`. Daca **folderul de pe disc lipseste**, curl esueaza mut si in log apare doar
|
||||
`Fisierul NU s-a salvat pe disc.` — verifica intai directorul, nu reteaua.
|
||||
|
||||
Verificari rapide (read-only, din `contafin_oracle`):
|
||||
|
||||
```sql
|
||||
-- calea configurata
|
||||
select directory_name, directory_path from all_directories where directory_name like 'UPD%';
|
||||
-- fisierul chiar exista pe disc?
|
||||
select dbms_lob.fileexists(bfilename('UPD_ROACONT','ROACONT-2.11.70.zip')) from dual;
|
||||
```
|
||||
|
||||
```sql
|
||||
-- directorul exista si e scriibil? ORA-29283 = cale OS inexistenta sau fara drept de scriere
|
||||
declare f utl_file.file_type; begin
|
||||
f := utl_file.fopen('UPD_USERREPORTS','__probe.txt','W'); utl_file.fclose(f);
|
||||
utl_file.fremove('UPD_USERREPORTS','__probe.txt');
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
URL-ul se testeaza direct cu `curl` de pe orice masina (`optiuni.UPD_URL_APP`, cu `|CUSTOMERID|`
|
||||
inlocuit din `sys.auth_detalii.detalii`); daca da 200, problema e local pe server.
|
||||
|
||||
## Comenzi OS pe serverul de baze de date
|
||||
|
||||
`sys.ExecuteScriptOS(<powershell>, <cale .ps1>)` creeaza un job scheduler `executable` — **asincron**,
|
||||
deci rezultatul se verifica prin polling, nu imediat. Scriptul se scrie cu
|
||||
`pack_utils_file.clob2fileX(<clob>, 'DMPDIR', '<nume>.ps1')`. Utila cand ai doar acces Oracle
|
||||
(ex. tunel SSH), fara RDP:
|
||||
|
||||
```sql
|
||||
declare lcPS server_info.value%type; begin
|
||||
select value into lcPS from server_info where upper(name)='POWERSHELLPATH';
|
||||
pack_utils_file.filedelete('DMPDIR','x.ps1');
|
||||
pack_utils_file.clob2fileX('New-Item -ItemType Directory -Force -Path ''D:\...'' | Out-Null',
|
||||
'DMPDIR','x.ps1');
|
||||
sys.ExecuteScriptOS(lcPS, 'C:\DMPDIR\x.ps1');
|
||||
end;
|
||||
/
|
||||
```
|
||||
|
||||
## Emailuri: log de actualizare vs buletin informativ
|
||||
|
||||
Sunt **doua emailuri diferite, trimise de doua masini diferite** — se confunda usor.
|
||||
|
||||
| | Log de actualizare | Buletin informativ |
|
||||
|---|---|---|
|
||||
| Cine trimite | baza de date, `PACK_UPDATE.EmailLog` (`UTL_SMTP` direct catre `EMAIL_SMTP:EMAIL_PORT`, `AUTH LOGIN`) | **serverul de update** (ASP.NET); baza doar face un GET pe `optiuni.UPD_URL_BULETININF` (cu `|CUSTOMERID|`) prin `PACK_UTILS.URL2Clob`, din `UpdateApp` |
|
||||
| Destinatari | `server_info.EMAIL_TO` + `EMAIL_CC` | configurati pe serverul de update, **nu** in `server_info` (ex. `office@romfast.ro`) |
|
||||
| Subiect / continut | `Actualizare ROA dd.mm.yyyy hh24:mi:ss`; liniile din `UPD_LOG`, text simplu separat cu TAB | compus de serverul de update |
|
||||
| In `UPD_LOG` | erorile SMTP: `EROARE: utl_smpt ERROR CODE ...` | raspunsul HTTP, verbatim (ex. `ERR-1-BULETIN INFORMATIV NU S-A TRIMIS. MOTIVUL: Error: 1429`) |
|
||||
|
||||
Detalii care conteaza la depanare:
|
||||
|
||||
- **`EMAIL_CC` nu produce un antet `Cc:`.** Codul il concateneaza cu virgula la `EMAIL_TO` si trimite
|
||||
`RCPT TO` pentru toti; antetul e un singur `To: <toti>`. Deci un email primit *in Cc* nu vine de la
|
||||
`EmailLog`.
|
||||
- **`EMAIL_FROM` e per server de client** (`roaupdate-<client>@romfast.ro`) si difera de contul
|
||||
autentificat, care e acelasi peste tot (`EMAIL_USERNAME = roaupdate@romfast.ro`). Expeditorul e
|
||||
singurul indiciu din email despre serverul care l-a trimis. Daca `EMAIL_FROM` lipseste, se compune
|
||||
din `UTL_INADDR.get_host_name`.
|
||||
- **Un buletin esuat nu opreste nimic**: raspunsul `ERR-1-...` e text normal, se scrie in `UPD_LOG` si
|
||||
actualizarea merge mai departe. Doar exceptiile HTTP ajung ca `ERR: <url> ...`.
|
||||
- **Un SMTP picat, in schimb, opreste tot** — `EmailLog` ridica `ORA-20000` care mascheaza eroarea
|
||||
reala (vezi „Capcane" mai sus). E singurul loc din lantul de email care are voie sa arunce.
|
||||
|
||||
## Configurare (CONTAFIN_ORACLE)
|
||||
|
||||
- `server_info`: `POWERSHELLDOWNLOAD`, `POWERSHELLPATH`, `POWERSHELLTIMEOUT`, `CURLPATH`,
|
||||
`SQLPLUSPATH`, `EMAIL_METHOD`/`EMAIL_SMTP`/`EMAIL_PORT`/`EMAIL_USERNAME`/`EMAIL_PASSWORD`/
|
||||
`EMAIL_FROM`/`EMAIL_TO`.
|
||||
- `optiuni`: `UPD_URL_APP`, `UPD_URL_DATABASE`, `UPD_URL_BULETININF` (daca lipsesc, pachetul
|
||||
foloseste URL-uri implicite din cod).
|
||||
|
||||
## Conectare la serverul unui client
|
||||
|
||||
Tunel SSH pe 1521 + alias TNS pe `127.0.0.1` in `D:\ROA\instantclient_19_18\tnsnames.ora`
|
||||
(ex. `ROA_ROMCONSTRUCT`), utilizator `contafin_oracle`. Vezi `oracle_export.md` pentru client si
|
||||
capcana de encoding; parolele stau in `COMUN\docs\local\oracle.md` (neversionat in git).
|
||||
|
||||
Serverele de client pot fi Oracle 10g: unele coloane din `dba_scheduler_*` lipsesc
|
||||
(`dba_scheduler_running_jobs.last_start_date`) — foloseste `dba_scheduler_job_run_details`.
|
||||
143
docs/depanare-spatiu-oracle.md
Normal file
143
docs/depanare-spatiu-oracle.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# Depanare spatiu Oracle la clienti
|
||||
|
||||
```powershell
|
||||
powershell -File COMUN\utile\diag_spatiu.ps1 -Alias <ALIAS_TNS> [-Disc] [-SysPassword <parola>] [-Top 30]
|
||||
```
|
||||
|
||||
Strict read-only in afara lui `-Disc` (singura parte care scrie: un `.ps1` temporar in `DMPDIR`,
|
||||
lansat cu `sys.ExecuteScriptOS` si sters la final). Actiunile de curatare sunt doar **sugerate**,
|
||||
niciodata executate. 8 sectiuni: conexiune/versiune (CDB-PDB), tablespace + top segmente, audit,
|
||||
alert log/trace/ADR, archivelog/FRA, disc server, alti mancatori de spatiu, verdict.
|
||||
|
||||
Pentru actualizarea blocata de spatiu, punctul de plecare e `depanare-pack-update.md`.
|
||||
|
||||
## Jobul automat `DIAGSPATIU_ZILNIC` (SVN r17969)
|
||||
|
||||
Echivalentul in baza al scriptului de mai sus, rulat zilnic la 06:00 de la fiecare client:
|
||||
`co_2026_08_03_02` (tabela `DIAG_SPATIU_LOG`, istoric purjat la 90 zile), `co_2026_08_03_03`
|
||||
(`PACK_DIAG_SPATIU`), `co_2026_08_03_04` (jobul), `sys_2026_08_03_05` (granturi). Praguri identice
|
||||
cu `diag_spatiu.ps1`; **email doar la prag depasit**, tacere completa altfel. Sursa de referinta:
|
||||
`COMUN\docs\PACK_DIAG_SPATIU.pck`.
|
||||
|
||||
Sectiunile informative (recyclebin, UNDO, TEMP, istoric statistici/scheduler, top segmente, audit
|
||||
SYS) se scriu doar cand exista deja o alerta — dau context, nu alerteaza singure.
|
||||
|
||||
`co_2026_08_20_01_DIAG_SPATIU_PACK` (20.08.2026) inchide doua gauri prin care o baza blocata putea
|
||||
sa nu alerteze niciodata:
|
||||
|
||||
- **tablespace fara autoextend**: `dba_data_files.maxbytes` e 0, iar conditia `max_bytes > 0` il
|
||||
scotea complet din verificare, oricat de plin ar fi fost. Acum plafonul e
|
||||
`GREATEST(maxbytes, bytes)`, deci pentru un datafile fix maximul e chiar spatiul alocat. In log,
|
||||
maximul 0 se scrie `fara autoextend`, nu `0MB`.
|
||||
- **disc plin sub datafile autoextensibil**: tablespace-ul arata zeci de GB "poate creste", dar
|
||||
autoextend-ul pica. Sectiunea `DISC` are prag propriu (`tnPragDiscMb`, implicit 2048 MB liberi) si
|
||||
ruleaza mereu, prima; alerta ei deschide si sectiunile informative (`Verifica` o primeste prin
|
||||
`tnAlerteInitiale`). Inainte rula doar daca exista deja o alerta, deci nu putea declansa una.
|
||||
|
||||
`co_2026_08_06_08_DIAG_SPATIU_PACK` + `sys_2026_08_06_07_DIAG_SPATIU_GRANT3` (06.08.2026) scriu la
|
||||
top segmente si **tabela/coloana din care provine segmentul** (`DetaliuSegment`: `DBA_LOBS`,
|
||||
`DBA_LOB_PARTITIONS`, `DBA_INDEXES`; segmentele temporare se marcheaza ca atare) — fara asta un
|
||||
`SYS_LOB0000630560C00017$$` de 4 GB in email nu spune nimic, iar serverul clientului nu e accesibil
|
||||
direct. Atentie: pentru `LOB PARTITION`, `dba_segments.segment_name` e `lob_name`, nu
|
||||
`lob_partition_name`.
|
||||
|
||||
Emailurile ajung pe `marius.mutu@romfast.ro`, cate un expeditor per client
|
||||
(`roaupdate_<client>@romfast.ro`); citirea lor: `email-thunderbird.md`.
|
||||
|
||||
`co_2026_08_06_01_DIAG_SPATIU_PACK` (06.08.2026) corecteaza doua lucruri vazute pe primele rulari:
|
||||
|
||||
- **pragul absolut (2048 MB) nu se mai aplica tablespace-urilor al caror maxim e sub el** — orice
|
||||
`UNDOTBS`/`SYSTEM` plafonat la 500–2048 MB alerta zilnic, prin definitie; acolo ramane doar garda
|
||||
relativa de 15%.
|
||||
- **emailul contine tot logul rularii** (alertele intai, apoi toate randurile din `DIAG_SPATIU_LOG`,
|
||||
cu `!` pe cele peste prag, sortate pe sectiune si valoare descrescator), nu doar un pointer catre
|
||||
tabela. Corpul e plafonat la 30000 de caractere (`EmailDiagSpatiu` lucreaza pe `VARCHAR2(32000)`),
|
||||
cu marcaj `... restul in DIAG_SPATIU_LOG` la depasire.
|
||||
|
||||
## Mecanisme reutilizabile (din investigatia pentru job)
|
||||
|
||||
- **`CONTAFIN_ORACLE.SERVER_INFO`** tine parolele `PASSWORD_SYS`/`PASSWORD_CONTAFIN_ORACLE`
|
||||
(zip+base64, nu criptare), caile `SQLPLUSPATH`/`POWERSHELLPATH`/`DMPDIR`, cheile `EMAIL_*` si
|
||||
cache-ul `VERSIUNE_<SCHEMA>`. Parola se citeste cu `PACK_UPDATE.GetSchemaParola('<SCHEMA>')`
|
||||
(decodeaza doar pentru `SYS` si `CONTAFIN_ORACLE`; pentru schemele de firma intoarce
|
||||
`'ROMFASTSOFT'` hardcodat).
|
||||
- **Rulare ca `SYS` din PL/SQL**: scrii un `.sql` in `DMPDIR` cu `connect sys/<parola>@ROA as
|
||||
sysdba` + `spool`, il lansezi cu `sys.UpdateSQLPLUS` si astepti fisierul de iesire; pentru OS,
|
||||
`sys.ExecuteScriptOS` (PowerShell). Ambele sunt asincrone (job `dbms_scheduler` de tip
|
||||
`executable`, auto-drop) — mecanismul folosit si de `PACK_UPDATE.UpdateDatabaseSqlPlus`. Fisierele
|
||||
temporare au nume proprii, ca sa nu se bata cu `script_master.sql` al actualizarii.
|
||||
- **`PACK_UPDATE.EmailLog` nu e reutilizabila** pentru alt continut: subiectul e hardcodat
|
||||
("Actualizare ROA ...") si corpul vine din `UPD_LOG`. Pentru alte alerte, bloc `UTL_SMTP` propriu
|
||||
care citeste aceleasi chei `EMAIL_*`.
|
||||
- **Scripturile `sys_*`** se aplica automat, ca orice `co_`/`ff_`: prefixul e recunoscut in
|
||||
`PACK_UPDATE.UpdateSchema*`, schema `SYS` se actualizeaza **prima**, iar `UpdateVersiune` isi
|
||||
scrie randul in `CONTAFIN_ORACLE.versiune` (schema `SYS` n-are tabela proprie). Deci un `sys_`
|
||||
livrat in aceeasi zi ruleaza inaintea scripturilor `co_` care depind de el.
|
||||
|
||||
## Ce umple spatiul, in ordinea frecventei
|
||||
|
||||
- **Tablespace cu `maxbytes` atins** — nu "disc plin", ci un plafon pus la instalare. Pe XE limita
|
||||
de 11/12 GB e pe *date utilizator*, nu pe `SYSTEM`.
|
||||
- **`SYSAUX`** — SQL Tuning Sets (`wri$_sqlset_*`), AWR, audit policies active pe un PDB nou.
|
||||
- **Fisierele `.aud`** din `audit_file_dest` (`adump`) — zeci de mii, niciodata curatate; **nu se vad
|
||||
din SQL**, doar cu `-Disc`.
|
||||
- **Alert log / trace / incident** (`diagnostic_dest`) — se purja cu `adrci purge`.
|
||||
- **FRA plina cu `log_mode=ARCHIVELOG`** → `ORA-00257`/`ORA-19809`; baza se blocheaza brusc, fara
|
||||
eroare vizibila in aplicatie.
|
||||
- Recyclebin, `UNDO` umflat, istoric statistici/scheduler, `TEMP`.
|
||||
- **Tabele de log ale aplicatiei** care cresc nelimitat (tiparul `SYS.INFO` de pe SIGMA) — apar in
|
||||
raportul de top segmente, numele difera per client.
|
||||
|
||||
## Cazuri
|
||||
|
||||
- **Rompetrol Energy** (XE 21c): `ORA-12954`, limita de 12 GB pe `dba_data_files` atinsa. `SYSAUX`
|
||||
umflat la 7.8 GB din SQL Tuning Sets (~5 GB) + AWR + audit policies. `TRUNCATE wri$_sqlset_*` a
|
||||
eliberat segmentele, dar `RESIZE` a picat cu `ORA-03297` (`SYSAUX` nu se shrink pe XE 21c) →
|
||||
singura solutie a fost **recrearea PDB-ului**, 13.5 GB → 3 GB. Detalii:
|
||||
`E:\proiecte\ROMFASTSQL\proxmox\lxc108-oracle\clienti\oracle-xe-21c\` (`README.md`,
|
||||
`depanare-ora-12954-spatiu.md`).
|
||||
- **ROA_CENTRAL** (`ORA-65114`, 02.08.2026): acelasi tipar, rezolvat prin curatenie tintita in loc
|
||||
de recreare PDB; SQL-uri gata scrise in acelasi repo (`docs/curatenie-spatiu-oracle.sql`).
|
||||
- **SIGMA** (03.08.2026): `SYSTEM` plafonat la 600 MB — vezi `depanare-pack-update.md`.
|
||||
- **VADECO** (XE 11.2, 20.08.2026): actualizarea a picat cu `ORA-00604` + `ORA-01654: unable to
|
||||
extend index SYS.I_IDL_CHAR1 in tablespace SYSTEM` la un `create package body` — eroarea n-are
|
||||
legatura cu scriptul: `IDL_CHAR$` e locul unde Oracle scrie codul PL/SQL. `SYSTEM` era 600 MB
|
||||
alocat cu `maxsize` tot 600 MB (autoextend pornit, dar la plafon), din care ~207 MB doar
|
||||
`SOURCE$`/`IDL_*` si 41 MB `SYS.INFO`. Deblocare: `alter database datafile '...\SYSTEM.DBF'
|
||||
autoextend on next 50m maxsize 2048m` (pe XE plafonul de 11 GB e pe date utilizator, nu pe
|
||||
`SYSTEM`), apoi reluarea actualizarii si `sys_2026_08_08_02` pentru `SYS.INFO`. Jobul de
|
||||
diagnostic n-ar fi ajutat: batch-ul murise inainte de `co_2026_08_03_02/03/04`, deci nu era
|
||||
instalat.
|
||||
|
||||
## Capcane
|
||||
|
||||
- **Segmentele `TEMPORARY` dintr-un tablespace permanent nu dispar intotdeauna la restart** (ACN,
|
||||
06.08.2026: 1.3 GB ramasi si dupa repornirea serviciului). Daca `v$sort_usage` e gol, sunt orfane
|
||||
si se curata fortat, ca `SYS`: `alter session set events 'immediate trace name DROP_SEGMENTS level
|
||||
<ts#+1>'` (`ts#` din `v$tablespace`) — la ACN au disparut instantaneu, cu tot spatiul recuperat.
|
||||
Daca nici asa nu pleaca, apartin unui DDL neterminat — cauta `SYS_JOURNAL%` (index online) sau
|
||||
obiecte `INVALID/UNUSABLE` in schema respectiva.
|
||||
- **`shrink space` pe un LOB cere ASSM**; pe un tablespace MSSM da `ORA-10635` (cazul `ROA` la ACN).
|
||||
Echivalentul care merge: `alter table t move lob (col) store as (tablespace <ts>)` — reconstruieste
|
||||
segmentul, tine tabela blocata cat dureaza si cere spatiu liber cat segmentul mutat.
|
||||
- **Privilegiile `ANY` nu se aplica pe obiectele din schema `SYS`** cat timp
|
||||
`O7_DICTIONARY_ACCESSIBILITY=FALSE` — orice curatare acolo cere `SYSDBA`.
|
||||
- Parola `SYS` e de obicei cea generica (vezi `COMUN\docs\local\oracle.md`), dar **nu la toti
|
||||
clientii** (ex. ROMCONSTRUCT) — cand nu merge, se ia cu `PACK_UPDATE.GetSchemaParola('SYS')`.
|
||||
`-SysPassword` ramane optional: diagnosticul de baza merge complet fara el, doar sectiunile
|
||||
SYSDBA se sar.
|
||||
- **Rolurile nu se aplica in pachete cu drepturi de definitor**: un pachet care refera static
|
||||
`dba_*`/`v$*` iese `INVALID` la clientul care are accesul doar prin rolul `DBA`, chiar daca
|
||||
aceleasi interogari merg din SQL*Plus. De aceea granturile directe din `sys_2026_08_03_05`.
|
||||
Lantul de actualizare **nu** se opreste in acest caz: `sqlplus` iese cu cod 0 la eroare de
|
||||
compilare, deci se vede doar ca pachet invalid + job cazut.
|
||||
- **Curatenia poate esua din lipsa de spatiu** (`DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL` a picat asa la
|
||||
Rompetrol): intai ridici plafonul, apoi cureti.
|
||||
- `RESIZE` pe datafile da `ORA-03297` daca extentele folosite nu sunt la coada fisierului — un
|
||||
`DELETE` fara `MOVE`/`SHRINK` nu recupereaza MB.
|
||||
- Dimensiunile reale ale fisierelor de pe disc nu se vad din SQL — `-Disc`, prin `ExecuteScriptOS`.
|
||||
- **`-Disc` merge doar pe servere Windows** (`ExecuteScriptOS` lanseaza PowerShell). Pe Linux
|
||||
expira curat dupa 60s, cu mesaj.
|
||||
- **`MAX_PDB_STORAGE` se citeste doar de pe un alias care tinteste radacina CDB.** De pe un
|
||||
serviciu de PDB (cazul obisnuit al aliasurilor din `tnsnames.ora`), `alter session set
|
||||
container=CDB$ROOT` da `ORA-01031` — e nevoie de un alias separat spre radacina.
|
||||
@@ -26,20 +26,20 @@ $p = Start-Process 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe' -
|
||||
$p.WaitForExit(120000); if (!$p.HasExited) { $p.Kill() }
|
||||
```
|
||||
- `-A` ignora config.fpw implicit, `-T` sare peste splash; **ambele obligatorii** - fara `-T`
|
||||
procesul ramane pe ecranul de intampinare (simptom identic cu o eroare de compilare).
|
||||
Un `-c<cale>` explicit (lipit de flag) e preluat chiar si impreuna cu `-A`.
|
||||
- **SAFETY**: sub `-A` porneste ON, deci primul `STRTOFILE` peste un log existent (sau
|
||||
`COMPILE` peste un `.err`/`.fxp` existent) scoate dialogul modal "overwrite?" si procesul
|
||||
pare agatat. Pune `SET SAFETY OFF` ca PRIMA linie din script si/sau `SAFETY=OFF` +
|
||||
`RESOURCE=OFF` intr-un config.fpw propriu pasat cu `-c`. Verificare: logheaza
|
||||
`SET("SAFETY")`/`SET("RESOURCE")` la start.
|
||||
procesul ramane pe ecranul de intampinare (simptom identic cu o eroare de compilare). `-c<cale>`
|
||||
explicit (lipit de flag) e preluat si cu `-A`.
|
||||
- **SAFETY**: sub `-A` porneste ON - primul `STRTOFILE` peste un log existent (sau `COMPILE` peste
|
||||
un `.err`/`.fxp` existent) scoate dialogul modal "overwrite?" si procesul pare agatat. Pune
|
||||
`SET SAFETY OFF` ca PRIMA linie din script si/sau `SAFETY=OFF`+`RESOURCE=OFF` intr-un config.fpw
|
||||
propriu pasat cu `-c`. Verificare: logheaza `SET("SAFETY")`/`SET("RESOURCE")` la start.
|
||||
- In script: logare cu STRTOFILE (nu WAIT WINDOW / debugger - nu exista consola);
|
||||
`ON ERROR DO <handler> WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()` care logheaza si
|
||||
continua (mimeaza ErrorHandler); `QUIT` obligatoriu la final.
|
||||
- `LINENO()` din handler e relativ la inceputul metodei: linia in `.vc2` = linia raportata +
|
||||
linia `PROCEDURE`.
|
||||
- Nu rula cu IDE-ul sau exe-ul aplicatiei deschis (lock pe binare); sterge `.fxp`-ul vechi
|
||||
daca ai editat scriptul intre rulari.
|
||||
- Nu rula cu IDE-ul sau exe-ul aplicatiei deschis (lock pe binare); sterge `.fxp`-ul vechi dupa
|
||||
editarea scriptului - altfel VFP ruleaza codul vechi din `.fxp` fara niciun semn (testul poate
|
||||
trece fals; se prinde doar cand lipseste din log o linie scrisa doar de codul nou).
|
||||
- Forme modale: `Show(1)` blocheaza. Replica in script doar liniile relevante din Show, sau
|
||||
seteaza `WindowType = 0`.
|
||||
|
||||
@@ -67,7 +67,7 @@ Cel mai ieftin test dupa o modificare: `COMPILE` headless, fara aplicatie si far
|
||||
|
||||
## 5. Bisectia versiunilor de clase (regresii)
|
||||
|
||||
Cand un bug apare "de azi", compara cu clasa veche fara a atinge SVN:
|
||||
Cand un bug apare "de azi", compara cu clasa veche fara sa atingi SVN:
|
||||
1. `git show <rev>:clase\fisier.vcx > temp\fisier.vcx` (+ `.vct`); pentru diff lizibil,
|
||||
`vcx2txt.ps1 -Source temp\fisier.vcx -CacheRoot temp\txt`.
|
||||
2. In harness incarca DOAR copia (`SET CLASSLIB TO temp\fisier.vcx`), **nu ADDITIVE peste cea
|
||||
@@ -87,8 +87,8 @@ Cand un bug apare "de azi", compara cu clasa veche fara a atinge SVN:
|
||||
pe copie crapa; recreeaza indexul dupa copiere. Acelasi lucru pentru cursorii creati intr-un
|
||||
test: trebuie sa aiba EXACT indecsii pe care ii creeaza fluxul real inainte de instantiere,
|
||||
altfel ordinea/logica difera si testul da rezultat fals.
|
||||
- **Un grid isi pierde TOATE coloanele** (`ColumnCount` devine 0, fara eroare in log) daca un
|
||||
ControlSource crapa la re-evaluare in timp ce coloanele sunt atinse programatic (ex. font per
|
||||
- **Un grid isi pierde TOATE coloanele** (`ColumnCount` devine 0, fara eroare in log) daca
|
||||
ControlSource crapa la re-evaluare cat timp coloanele sunt atinse programatic (ex. font per
|
||||
coloana la Init). Simptome in aval: `attachtogrid` copiaza 0 coloane, apoi `calctotal` da
|
||||
"Property <cColWithLabel> is not found". Similar, un cursor legat la grid recreat de Init
|
||||
lasa grid-ul fara coloane (eroare 1925).
|
||||
@@ -98,33 +98,56 @@ Cand un bug apare "de azi", compara cu clasa veche fara a atinge SVN:
|
||||
- **Coloana de grid cu ControlSource EXPRESIE (nu camp) cere `Bound = .F.`** Fara el: eroare 9
|
||||
"Data type mismatch" la `CREATEOBJECT`-ul formei (faza de constructie, raportata la linia
|
||||
apelanta, Details gol).
|
||||
- **Erorile de instantiere sunt raportate la linia `CREATEOBJECT`, nu la `.Init`**: daca
|
||||
- **Erorile de instantiere se raporteaza la linia `CREATEOBJECT`, nu la `.Init`**: daca
|
||||
`Procedure` = scriptul apelant, eroarea vine din evaluarea definitiei clasei (`ADD OBJECT ...
|
||||
WITH RowSource`, ControlSource-expresie), pentru ca bind-ul controalelor native se rezolva la
|
||||
WITH RowSource`, ControlSource-expresie) - bind-ul controalelor native se rezolva la
|
||||
CONSTRUCTIE, inainte de `Init`.
|
||||
- **Literal string > 255 caractere = eroare de COMPILARE, nu de runtime** (masurat 24.07.2026:
|
||||
255 trece, 256 pica). Mesaj: `Unrecognized command verb` daca linia incepe cu un apel de
|
||||
metoda, `Command contains unrecognized phrase/keyword` la o atribuire. Insidios: restul
|
||||
programului ruleaza, doar linia aceea lipseste din `.fxp` si da eroare 16 cand se ajunge la
|
||||
ea. De aceea SQL-ul lung se scrie cu `TEXT TO <var> [TEXTMERGE] NOSHOW ... ENDTEXT` sau
|
||||
concatenat. Verificare: `awk 'length($0) > 260 {print NR": "length($0)}' fisier.prg`.
|
||||
- **Literal string > 255 caractere = eroare de COMPILARE, nu runtime** (255 trece, 256 pica).
|
||||
Mesaj: `Unrecognized command verb` daca linia incepe cu un apel de metoda,
|
||||
`Command contains unrecognized phrase/keyword` la o atribuire. Insidios: restul programului
|
||||
ruleaza, doar linia lipseste din `.fxp` si da eroare 16 cand se ajunge la ea. De aceea SQL-ul
|
||||
lung se scrie cu `TEXT TO <var> [TEXTMERGE] NOSHOW ... ENDTEXT` sau concatenat. Verificare:
|
||||
`awk 'length($0) > 260 {print NR": "length($0)}' fisier.prg`.
|
||||
- **Linie de COD (nu doar literal string) prea lunga intr-o metoda de clasa `.vc2` poate arunca
|
||||
eroarea 11 ("Function argument value, type, or count is invalid") pe PRIMA instructiune a
|
||||
metodei, nu pe linia vinovata** - simptom derutant. Se exclude prin diagnostic: aceeasi
|
||||
expresie merge normal la nivel de program, in alta clasa, intr-o subclasa cu metoda noua, si
|
||||
pe instanta virgina - deci nu tine de tipul datelor, de context sau de clasa parinte. Reper
|
||||
practic: linii preexistente >200 caractere intr-o clasa mare functioneaza pana la ~250; pragul
|
||||
real e in jur de 255, ca la literalii de string. Remediu: sparge expresia in pasi cu variabile
|
||||
locale. Verificare (comparat intre fisierul curent si un backup anterior):
|
||||
```powershell
|
||||
$l=[IO.File]::ReadAllLines($p,[Text.Encoding]::GetEncoding(28591))
|
||||
for($i=0;$i -lt $l.Length;$i++){ if($l[$i].Length -gt 200){ "{0}: len={1}" -f ($i+1), $l[$i].Length } }
|
||||
```
|
||||
- **Un UDF care citeste campul curent (`Nvl(camp,0)=1` sau similar) nu e de incredere intr-o
|
||||
clauza de filtrare** (`SELECT ... WHERE`, `LOCATE FOR`, `SCAN FOR`, `DELETE FOR`) - pointerul
|
||||
nu e garantat pe randul evaluat la fiecare apel, deci filtrul devine practic o valoare
|
||||
constanta (nu se declanseaza deloc, sau loveste tot). Simptome vazute: comasare de randuri
|
||||
care nu se mai producea deloc; test agatat. Remediu: in clauze de filtrare foloseste expresia
|
||||
INLINE pe camp (`Nvl(camp,0) <> 1`); pastreaza helper-ul doar in cod procedural (`If`,
|
||||
`Replace` pe randul curent), unde pointerul e garantat pozitionat.
|
||||
|
||||
- **`SET PROCEDURE TO x.prg`**: in `.exe` se rezolva din modulele compilate (orice `.prg` din
|
||||
`.pjx`), din IDE doar prin `SET PATH`. O cale lipsa din `SET PATH` se vede deci doar necompilat,
|
||||
iar in `Try` trece tacut.
|
||||
|
||||
## 7. Capcane la SCRIEREA scriptului de test
|
||||
|
||||
- **`SET SAFETY OFF` in primele linii, INAINTE de orice `STRTOFILE`/`CREATE CURSOR`** (plus
|
||||
`SET TALK OFF`). Fara el VFP deschide dialogul de confirmare la suprascrierea fisierului de
|
||||
log, iar headless dialogul blocheaza procesul pana la timeout. Suitele existente il au deja -
|
||||
capcana apare la scripturile ad-hoc, scrise repede pentru o masuratoare.
|
||||
`SET TALK OFF`). Fara el VFP deschide dialogul de confirmare la suprascriere, iar headless
|
||||
dialogul blocheaza procesul pana la timeout. Suitele existente il au deja - capcana apare la
|
||||
scripturile ad-hoc, scrise repede pentru o masuratoare.
|
||||
- **`DEFINE CLASS ... ENDDEFINE` nu poate sta la mijlocul programului principal.** Toate liniile
|
||||
de DUPA `ENDDEFINE` dau "Statement is not in a procedure" (vezi `<script>.ERR`); scriptul
|
||||
ruleaza doar pana acolo si se opreste silentios, fara sa ajunga la `QUIT` - simptom: vfp9.exe
|
||||
pare agatat la nesfarsit. Pune orice `DEFINE CLASS` auxiliar la FINALUL fisierului.
|
||||
de DUPA `ENDDEFINE` dau "Statement is not in a procedure" (vezi `<script>.ERR`); scriptul se
|
||||
opreste silentios, fara sa ajunga la `QUIT` - simptom: vfp9.exe pare agatat la nesfarsit. Pune
|
||||
orice `DEFINE CLASS` auxiliar la FINALUL fisierului.
|
||||
- **Dummy-uri cu metode**: `CREATEOBJECT('Custom')` + `AddProperty()` adauga doar PROPRIETATI.
|
||||
Daca clasa testata apeleaza `goExecutor.oExecute(...)`, dummy-ul trebuie sa fie
|
||||
`DEFINE CLASS dummyexecutor AS Custom` cu `PROCEDURE oExecute` reala.
|
||||
- **Diagnostic "script agatat"**, in ordine: (1) exista `<script>.ERR` langa `.prg`? => s-a
|
||||
oprit la compilare; (2) CPU-ul procesului ~0 dupa cateva secunde (`Get-Process | select CPU`)
|
||||
=> asteapta un dialog modal, nu proceseaza; confirma enumerand ferestrele procesului cu
|
||||
=> asteapta un dialog modal; confirma enumerand ferestrele procesului cu
|
||||
`EnumWindows`/`GetWindowText`/`GetWindowThreadProcessId` (`Add-Type`, user32) filtrat pe PID -
|
||||
daca vezi doar fereastra principala + "Command", nu e dialog, cauta alta cauza (tipic `-T`
|
||||
lipsa). Confirma mereu cauza inainte de a schimba scriptul.
|
||||
|
||||
41
docs/email-thunderbird.md
Normal file
41
docs/email-thunderbird.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Citirea emailurilor (Thunderbird Portable)
|
||||
|
||||
Conectorul Gmail din Claude vede **doar** `mmarius28@gmail.com`. Conturile de lucru
|
||||
(`marius.mutu@romfast.ro` etc.) nu sunt acolo — se citesc local, din mbox-urile Thunderbird:
|
||||
|
||||
```
|
||||
D:\UTIL\portable\PortableApps\ThunderbirdPortable\Data\profile\ImapMail\<cont>\INBOX
|
||||
```
|
||||
|
||||
Conturi active (dupa `LastWriteTime`): `mail.romfast.ro` (~36 MB, contul principal) si
|
||||
`mail.romfast-1.ro` (~108 MB). Restul (`seanet.ro`, `romfast-4.ro`, `imap.googlemail.com`, …)
|
||||
sunt vechi de ani.
|
||||
|
||||
```powershell
|
||||
powershell -File COMUN\utile\citeste_email.ps1 -Cauta 'Diagnostic spatiu' -Ultimele 10
|
||||
powershell -File COMUN\utile\citeste_email.ps1 -Nr <linie> [-Linii 200]
|
||||
```
|
||||
|
||||
Prima forma listeaza `Cont / Linie / Data / De_la / Subiect` (filtru `-Cauta` pe subiect **sau**
|
||||
expeditor, `-Cont mail.romfast.ro` restrange la un cont); a doua tipareste mesajul care incepe la
|
||||
linia respectiva, pana la urmatorul separator mbox.
|
||||
|
||||
## Capcane
|
||||
|
||||
- **Nu da `Grep`/ripgrep pe folder**: `INBOX.sbd\Sent` are ~2.5 GB si cautarea expira.
|
||||
- **Numerotarea liniilor difera intre unelte** (`Select-String` vs `Get-Content` vs `StreamReader`)
|
||||
— mbox-ul are linii cu `\r` singur. Foloseste numarul dat de `citeste_email.ps1`, pentru ca
|
||||
`-Nr` citeste cu acelasi cititor; daca linia ceruta nu e inceput de mesaj, scriptul trece la
|
||||
contul urmator (`-Nr` fara `-Cont` cauta in toate).
|
||||
- Thunderbird tine fisierul deschis → citire doar cu `FileShare::ReadWrite` (scriptul o face).
|
||||
- Mesajele sunt in ordine cronologica, **cel mai nou la sfarsitul fisierului**; separatorul e
|
||||
`From - <data>`. Corpurile HTML/base64 se tipar brut — pentru ele ia doar `Content-Type` si
|
||||
primele linii, nu tot mesajul.
|
||||
|
||||
## Emailuri automate ROA
|
||||
|
||||
| Expeditor | Ce e |
|
||||
|---|---|
|
||||
| `roaupdate_acn@`, `roaupdate-sigma@`, `roaupdate-clever@`, `roaupdate-automotive@` … | jobul `DIAGSPATIU_ZILNIC`, subiect `Diagnostic spatiu Oracle <BAZA> <data> <ora>`, cate un expeditor per client. Vezi `depanare-spatiu-oracle.md` |
|
||||
|
||||
Emailul vine **doar la prag depasit**; tacere = totul in regula.
|
||||
@@ -10,11 +10,21 @@ in IDE. `txt2vcx.ps1` cu `-CacheRoot` = `-ProjectRoot` (implicit). Pasul 0 de ma
|
||||
rularea `git_sync.ps1`; restul pasilor raman la fel. Fluxul cu cache extern (`vcx2txt.ps1` +
|
||||
`-CacheRoot` separat) ramane doar pentru proiectele nemigrate.
|
||||
|
||||
**Capcana: `git_sync.ps1` cu `-ProjectRoot` pe COMUN direct.** Lista implicita
|
||||
`-RoundtripExempt` are cai de forma `COMUN\clase\<f>.vcx` (raportate la radacina unei aplicatii,
|
||||
unde COMUN e subfolder) si se lipeste de `-ProjectRoot`. Cand radacina E chiar COMUN, caile nu
|
||||
mai potrivesc si clasele scutite (FFC/third-party cu `#INCLUDE`, ex. `oinventar.vcx`) raporteaza
|
||||
fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
|
||||
`git_sync.ps1 -ProjectRoot 'D:\ROA\ROAGEST\COMUN' -RoundtripExempt @('clase\accessibility.vcx',
|
||||
'clase\oinventar.vcx','clase\_gdiplus.vcx','clase\_reportlistener.vcx',
|
||||
'utile\foxcharts\foxcharts.vcx','utile\web\_webview.vcx')` - si apeleaza scriptul cu `&`, nu cu
|
||||
`powershell -File` (acolo lista nu se leaga ca array).
|
||||
|
||||
## Parametri per proiect (nemigrate, cache extern)
|
||||
|
||||
- **ROAGEST**: `-Project 'D:\ROA\ROAGEST\roagest.pjx' -ProjectRoot 'D:\ROA\ROAGEST'
|
||||
-CacheRoot 'D:\ROA\_vfp_textcache\roagest'`; procese de verificat inainte de write-back:
|
||||
`vfp9`, `roagest`; patch-uri de review in `docs/diff_runda<N>_<subiect>.patch`.
|
||||
-CacheRoot 'D:\ROA\_vfp_textcache\roagest'`; patch-uri de review in
|
||||
`docs/diff_runda<N>_<subiect>.patch`.
|
||||
|
||||
## Pasii unei runde
|
||||
|
||||
@@ -22,12 +32,17 @@ rularea `git_sync.ps1`; restul pasilor raman la fel. Fluxul cu cache extern (`vc
|
||||
`vcx2txt.ps1 -Project <pjx> -ProjectRoot <root> -CacheRoot <cache> -Types vcx,scx`
|
||||
1. Baseline: `Copy-Item <f>.vc2 <f>.vc2.pre_runda<N>.bak` (in cache; la runde succesive
|
||||
necomise, diff-ul fata de HEAD ar amesteca rundele).
|
||||
2. Editare byte-safe: PowerShell `[IO.File]::ReadAllText/WriteAllText(..., GetEncoding(1252))`;
|
||||
2. Editare byte-safe: PowerShell `[IO.File]::ReadAllText/WriteAllText(..., GetEncoding(1252))` -
|
||||
doar pentru round-trip pe octeti, NU pentru retastat literal diacritice (antetul zice
|
||||
`CPID="1252"`, dar octetii diacriticelor sunt de fapt cp1250: `conventie_encoding_cp1252.md`).
|
||||
NU tool-ul Edit/Write (UTF-8 strica diacriticele). Continut nou ASCII, TAB-uri ca in jur,
|
||||
fara reflow (format position-sensitive, proprietati alfabetizate). Valabil si pentru `.prg`.
|
||||
3. Patch review: `git diff --no-index <bak> <editat> > docs/diff_runda<N>_<subiect>.patch`
|
||||
(exit 1 = normal). Utilizatorul revizuieste FISIERUL de patch si aproba; write-back-ul
|
||||
(pasul 5) se face DOAR dupa aprobare. Commit doar dupa confirmare pe patch + test in IDE.
|
||||
(exit 1 = normal). Utilizatorul revizuieste FISIERUL de patch si aproba — aprobarea
|
||||
conditioneaza COMMIT-ul, nu write-back-ul: pasii 5 si 6 se fac imediat, fara sa astepti
|
||||
raspunsul (si pe `COMUN`), ca review-ul sa primeasca rezultate de test, nu o propunere
|
||||
netestata. Rollback daca patch-ul e respins sau modificarea nu merge: `git checkout` pe
|
||||
binare (`.vcx`+`.vct`) sau write-back din `*.pre_runda<N>.bak`.
|
||||
Comentariile in cod: conventia din `reguli_lucru.md` (punctul 2).
|
||||
Obligatoriu inainte de a preda patch-ul la review: skill-ul de code-review rulat pe bucatile
|
||||
de cod din diff (nu doar citire manuala) - prinde defecte gen IIF cu numar gresit de
|
||||
@@ -37,9 +52,14 @@ rularea `git_sync.ps1`; restul pasilor raman la fel. Fluxul cu cache extern (`vc
|
||||
dintr-un cursor in loc de Scan manual; butoane din cmd_butoane.vcx in loc de butoane ad-hoc).
|
||||
Inventarul comunelor: COMUN\docs\inventar-comun.md - se consulta si la pasul de plan/arhitectura,
|
||||
inainte de a scrie cod nou.
|
||||
4. Preconditie write-back: niciun proces vfp9/<exe proiect> (tin lock pe binar); nu se omoara.
|
||||
4. Preconditie write-back: binarul tinta sa nu fie blocat. `txt2vcx.ps1` verifica singur
|
||||
(`Test-ExclusiveAccess` pe `.vcx`+`.vct`) si refuza cu mesaj clar daca e lock. NU conteaza
|
||||
existenta altor instante `vfp9` — utilizatorul poate lucra in paralel in alt proiect VFP —
|
||||
si NU se omoara procese: cand lock-ul exista, se cere utilizatorului sa inchida sesiunea.
|
||||
5. Write-back: `txt2vcx.ps1 -TextFile <vc2> -ProjectRoot <root> -CacheRoot <cache>`
|
||||
(+ `-AllowComun` cu aprobare explicita pentru tinte COMUN — afecteaza toate aplicatiile ROA).
|
||||
(+ `-AllowComun` pentru tinte COMUN — afecteaza toate aplicatiile ROA, deci schimbarea in sine
|
||||
se propune explicit, dar write-back-ul local nu asteapta aprobarea; nimic nu pleaca la celelalte
|
||||
aplicatii pana la commit+push).
|
||||
Succes = fidelity-check trecut: binar cu mtime nou; `vcx2txt.ps1` ulterior il vede la zi.
|
||||
6. Teste finale pe cerinta initiala (cerinta Marius, valabila in toate proiectele VFP):
|
||||
dupa ultima runda, teste e2e (harness UI, pe fluxul real al utilizatorului) care verifica
|
||||
@@ -47,7 +67,8 @@ rularea `git_sync.ps1`; restul pasilor raman la fel. Fluxul cu cache extern (`vc
|
||||
dat de Marius, cu valorile lui asteptate — nu doar teste per-fix. Assert-uri pe continutul
|
||||
rezultatului (sume, campuri, randuri), nu pe efecte de suprafata ("a aparut un rand" nu e
|
||||
suficient).
|
||||
7. Backup-urile `.pre_runda*.bak` si patch-urile se sterg la curatenia de dupa commit.
|
||||
7. Curatenie dupa commit (backup-uri `.pre_runda*.bak`, patch-uri, artefacte de test):
|
||||
`powershell -File COMUN\utile\curatenie.ps1` — vezi regula 1 din `reguli_lucru.md`.
|
||||
|
||||
## Capcane
|
||||
|
||||
@@ -57,9 +78,24 @@ rularea `git_sync.ps1`; restul pasilor raman la fel. Fluxul cu cache extern (`vc
|
||||
- Metoda noua de clasa cere `*m: nume` in `*<DefinedPropArrayMethod>`; fara ea, prima salvare
|
||||
din IDE o arunca tacut, iar refresh-ul urmator absoarbe pierderea in cache (si in .bak-uri).
|
||||
Override-urile de metode de baza (Init, Show, hook-uri) nu au nevoie de `*m:`.
|
||||
- **Proprietate noua de clasa cere identic `*p: nume` in `*<DefinedPropArrayMethod>`** — nu doar
|
||||
valoarea in `*<PropValue>`. Fara `*p:`, valoarea se scrie in text, **trece fidelity-check-ul**
|
||||
(fidelity compara doar text-sursa cu text-regenerat) si ajunge in binar ca text, dar VFP nu o
|
||||
materializeaza pe obiect: `PEMSTATUS(o,'nume',5)` da `.F.` si orice acces cade cu eroarea 1734
|
||||
"Property ... is not found". Dovedit in ambele sensuri pe o clasa de proba izolata (cu `*p:` ->
|
||||
`.T.`, fara -> `.F.`).
|
||||
- **FoxBin2Prg sorteaza alfabetic cu `_` DUPA literele obisnuite**, nu in ordine ASCII brut (unde
|
||||
`'_' (0x5F) < 'v' (0x76)` pe litere mici). O intrare `*p:`/`*m:` scrisa de mana in ordine "ASCII
|
||||
corecta" pica fidelity-check-ul; ordinea canonica se citeste din textul regenerat in
|
||||
`<staging>\verify\*.vc2` (vezi punctul de mai jos despre pozitia metodelor noi — se aplica identic
|
||||
proprietatilor).
|
||||
- FoxBin2Prg NU pastreaza pozitia in text a unei metode noi: o regenereaza la pozitia
|
||||
alfabetica din `*<DefinedPropArrayMethod>`. O metoda scrisa in alta parte a fisierului
|
||||
face fidelity-check-ul sa pice. Sursa de adevar pentru relocare e textul regenerat din
|
||||
`<staging>\verify\` - muta metoda unde apare acolo si reia write-back-ul.
|
||||
- Salvarea din VFP IDE peste un binar scris de txt2vcx poate PIERDE si definitii `*m:` deja
|
||||
existente, desi corpurile PROCEDURE raman (patit pe ROAGEST: `import_adauga_factura.recalc_tva`,
|
||||
`import_nota.do_adauga/do_copie/do_reface`, 07.2026); simptom: crash la Createobject cu
|
||||
`import_nota.do_adauga/do_copie/do_reface`); simptom: crash la Createobject cu
|
||||
"Data type mismatch" raportat la linia apelanta. Dupa orice sesiune IDE pe clasa: refresh
|
||||
cache + compara lista `*m:` cu starea de dinainte.
|
||||
- Nu folosi *Project > Build* ca sa recompilezi un binar vizat: rebuild-ul recompileaza toate
|
||||
@@ -68,3 +104,8 @@ rularea `git_sync.ps1`; restul pasilor raman la fel. Fluxul cu cache extern (`vc
|
||||
fluxul text->bin punctual pe binarul vizat.
|
||||
- Subagentii delegati primesc regulile 2-5 in prompt si raporteaza unicitatea sirurilor
|
||||
inlocuite + rezultatul fidelity-check-ului.
|
||||
- Fisierele `.vc2`/`.sc2` sunt CRLF, dar here-string-urile PowerShell (`"...`r`n..."` sau
|
||||
`@"..."@`) produc LF simplu pe orice linie noua inserata daca nu incluzi explicit `` `r`n ``
|
||||
la fiecare capat de linie - rezultatul e un fisier cu sfarsituri de linie amestecate (CRLF pe
|
||||
continutul vechi, LF pe cel nou). Verificare finala obligatorie dupa orice scriere: numara
|
||||
octetii `0x0A` neprecedati de `0x0D` (LF izolati) - trebuie sa fie 0.
|
||||
|
||||
165
docs/flux-modificare-stergere-nota-jurnal.md
Normal file
165
docs/flux-modificare-stergere-nota-jurnal.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# Flux: modificare/stergere nota in Registrul Jurnal
|
||||
|
||||
Comportament CORECT (nu bug): la **modificarea** unei note din Registrul Jurnal, documentul
|
||||
original nu se suprascrie. Se marcheaza `sters = 1` pe randurile vechi (`ACT`/`RUL`/`RUL_OBINV`),
|
||||
apoi se scrie un document NOU cu alt `cod`, pastrand acelasi `id_fact`/`id_factd`. Ambele operatii
|
||||
ruleaza intr-o tranzactie manuala unica (commit sau rollback pe amandoua).
|
||||
|
||||
## Unde
|
||||
|
||||
- `afisjurcom.do_modifica` - `COMUN\clase\comun.vc2:2222-2562`. Deschide tranzactia manuala
|
||||
(`Thisform.do_deschide_tranzactie()`, linia 2448), apoi `oscrie_in_fisiere(2,...)` = STERGE
|
||||
(linia 2451), apoi `oscrie_in_fisiere(0,...)` = SCRIE (linia 2479), apoi
|
||||
`pack_contafin.finalizeaza_modificare_nota(...)` (2484-2486), apoi
|
||||
`Thisform.do_inchide_tranzactie(...)` (linia 2535) - commit daca tot ce a rulat inainte a
|
||||
reusit, rollback altfel.
|
||||
- `do_deschide_tranzactie`/`do_inchide_tranzactie` (`_frmbase`, `COMUN\clase\_frm_base.vc2:252,279`;
|
||||
varianta identica ca procedura globala in `COMUN\programe\oproceduri_rulaje.prg:287,303`):
|
||||
`SQLSetProp(gnHandle,'Transactions',2)` la deschidere, `SQLCOMMIT`/`SQLROLLBACK` +
|
||||
`SQLSetProp(...,'Transactions',1)` la inchidere.
|
||||
- `oscrie_in_fisiere.prg` (`COMUN\programe\oscrie_in_fisiere.prg`): `tnScrie_Sterge` 0=scriere,
|
||||
2=stergere. Apeleaza server-side `pack_contafin.init_scriere_act_rul_local` +
|
||||
`final_scriere_act_rul_local` -> `finalizeaza_scriere_act_rul`, care ruleaza `SCRIE_IN_ACT`
|
||||
(scriere) sau `STERGE_DIN_ACT` (stergere) din `PACK_CONTAFIN.pck`.
|
||||
- `PACK_CONTAFIN.STERGE_DIN_ACT` (`COMUN\docs\PACK_CONTAFIN.pck:1815-1859`):
|
||||
`UPDATE ACT SET STERS = 1 ... WHERE COD = tnCod` - marcheaza vechiul document, pe `cod`-ul vechi.
|
||||
- `PACK_CONTAFIN.SCRIE_IN_ACT` (`PACK_CONTAFIN.pck:630-901`): `LN_COD := pack_contafin.GET_COD()`
|
||||
(linia 648) aloca un `cod` nou; `UPDATE ACT_TEMP SET COD = LN_COD, ...` (linia 897) il scrie pe
|
||||
noul document - `ID_FACT` nu e atins, ramane cel din documentul original.
|
||||
- `PACK_CONTAFIN.finalizeaza_modificare_nota` (`PACK_CONTAFIN.pck:8601-8651`): aloca din nou
|
||||
`lnCodNou := pack_contafin.get_cod()` si actualizeaza pe codul nou `vanzari`
|
||||
(`pack_facturare.actualizeaza_vanzari`) si `atasamente_vanzari`. `nom_lucrari` se actualizeaza
|
||||
DOAR pentru `id_set IN (31003,31004,31005,31011)` (repune `id_fact`), nu general. `gest_inventar`
|
||||
NU se leaga de `cod`-ul nou - se identifica dupa `dataora_validat + an + luna` (cazul
|
||||
`id_set = 90101`, note de inventariere).
|
||||
|
||||
## Atentie: nu e valabil la fel pentru stergerea simpla
|
||||
|
||||
`afisjurcom.do_sterge` (`comun.vc2:2565-2724`) ofera doua optiuni (`xmenu`, linia 2625):
|
||||
- **Stergere document** (`lnOptiune = 1`): DOAR `OSCRIE_IN_FISIERE(2,...)` + `finalizeaza_stergere_nota`
|
||||
- marcheaza `sters = 1`, NU se creeaza document nou.
|
||||
- **Anulare document** (`lnOptiune = 2`): STERGE (linia 2698) + SCRIE (linia 2709, cu sumele puse pe
|
||||
0) - creeaza si document nou, la fel ca la modificare - dar aici cele doua apeluri NU sunt
|
||||
invelite intr-o tranzactie manuala comuna (nu apare `do_deschide_tranzactie`/
|
||||
`do_inchide_tranzactie` in `do_sterge`); fiecare `OSCRIE_IN_FISIERE` isi gestioneaza singur
|
||||
commit-ul (vezi `tlModificare`/`llManualTransactions` in `oscrie_in_fisiere.prg:111-165`).
|
||||
|
||||
## Ramura noua: editare factura de vanzare (VANZARI/VANZARI_DETALII)
|
||||
|
||||
Cand documentul modificat prin `frm_modific2024` are un rand corespunzator in `VANZARI`, clasa
|
||||
adauga o pagina noua in pageframe-ul de rulaje, `PAGE3 "Articole factura"`
|
||||
(`COMUN\clase\omodificari.vc2:8707`), cu un grid legat pe cursorul `tvd` (structura view-ului
|
||||
`VVANZARI_ARTICOLE`). Pe orice alt document (nota fara factura) formularul ramane neschimbat -
|
||||
pageframe-ul are `PageCount = 2`, ca azi.
|
||||
|
||||
Ramura e activa doar cand `COMUN\programe\ofacturare_editare.prg` e incarcat in `SET PROCEDURE`
|
||||
(verificat prin `"OFACTURARE_EDITARE" $ Upper(Set("Procedure"))`) - inregistrat la pornire de toate
|
||||
trei aplicatiile care folosesc `frm_modific2024`: `ROAFACTURARE\Programe\roafacturare.prg:214`,
|
||||
`ROACONT\Programe\roacont.prg:212`, `ROAGEST\Programe\roagest.prg:260`.
|
||||
|
||||
### Doua puncte de intrare
|
||||
|
||||
- `frm_facturi.do_editare_factura` (`COMUN\clase\ofacturare_comun.vc2:3715-3872`), actiune noua pe
|
||||
formularul de facturi din ROAFACTURARE. Refuza editarea daca documentul e sters, e proforma, nu e
|
||||
din luna curenta (`:3742-3755`), are referinte de incasari/plati (`ReferinteDocumenteNota`,
|
||||
`:3758`) sau a fost trimis in eFactura (`EsteInEFactura`, in `ofacturare_editare.prg`, `:3764`).
|
||||
Inainte de `Createobject([frm_modific2024])` incarca `crsArticoleFactura` cu
|
||||
`IncarcaArticoleFactura` (`:3793`), ca gridul din PAGE3 sa se lege o singura data pe cursorul deja
|
||||
plin.
|
||||
- `afisjurcom.do_modifica` (`COMUN\clase\comun.vc2:2222-2567`) - acelasi punct folosit pentru orice
|
||||
nota din Registrul Jurnal, neschimbat pentru documentele care nu sunt facturi de vanzare. Inainte
|
||||
de `Createobject`, `PregatesteArticoleFacturaEditare('tact')` (`:2436`, in
|
||||
`ofacturare_editare.prg`) cauta randul din `VANZARI` corespunzator notei (pe combinatiile
|
||||
`cod/nract/serie_act/dataact` din `tact`) si, daca il gaseste, pre-incarca articolele. Pe acest
|
||||
punct de intrare nu se verifica garda eFactura si nici cea de referinte de incasari/plati - doar
|
||||
restrictia de luna curenta, deja existenta pentru orice nota (`:2265-2268`). Diferenta e
|
||||
intentionata: garda de referinte protejeaza incasarile legate prin `id_fact` la operatia care
|
||||
sterge efectiv factura; pe editarea de sume din ROAFACTURARE se aplica pentru ca stergerea si
|
||||
rescrierea notei sunt parte din acelasi pas, dar pe editarea generica de note din Registrul
|
||||
Jurnal (care poate sa nu priveasca deloc o factura) nu se aplica.
|
||||
|
||||
Daca apelantul nu a putut pregati articolele dinainte, `frm_modific2024.Show` reface legatura prin
|
||||
`IncarcaVanzareDinNota` ca fallback si decide acolo daca arata `PAGE3`
|
||||
(`omodificari.vc2:14769-14794`).
|
||||
|
||||
### Scrierea, in aceeasi tranzactie manuala
|
||||
|
||||
La `buton = 1` (Terminat), pasul nou se adauga la coada secventei existente de
|
||||
stergere+scriere+realiniere, in aceeasi tranzactie manuala unica, identic pe ambele puncte de
|
||||
intrare (`ofacturare_comun.vc2:3828-3830`, `comun.vc2:2491-2493`):
|
||||
|
||||
```
|
||||
do_deschide_tranzactie()
|
||||
oscrie_in_fisiere(2,...) -- sterge nota veche (ACT/RUL)
|
||||
oscrie_in_fisiere(0,...) -- scrie nota noua, cod nou
|
||||
pack_contafin.finalizeaza_modificare_nota(...) -- realiniaza VANZARI.COD (actualizeaza_vanzari)
|
||||
ScrieArticoleFacturaEditate(tvanz.id_vanzare) -- NOU
|
||||
do_inchide_tranzactie(...)
|
||||
```
|
||||
|
||||
Agatarea ruleaza doar cand `tvanz` e deschis cu exact un rand (documentul are factura asociata).
|
||||
`VANZARI.ID_FACT` nu e atins de niciun pas al secventei - ramane cel alocat la emiterea initiala a
|
||||
facturii, la fel ca la orice alta nota (vezi "Implicatii practice"); doar `VANZARI.COD` se
|
||||
realiniaza pe codul nou al notei. Tot ce se leaga prin `id_fact` (`ANAF_EFACTURA`, `DOCUMENTE`,
|
||||
`ACT.id_factd`/`id_factc`) sau prin `ID_VANZARE` supravietuieste neschimbat unei reeditari; doar ce
|
||||
ar tine minte `cod`-ul vechi il pierde.
|
||||
|
||||
`pack_facturare.actualizeaza_vanzari`, apelata din `finalizeaza_modificare_nota`, face
|
||||
`UPDATE VANZARI_DETALII SET STERS = 0` pe tot documentul, fara nicio garda pe linie - reseteaza si
|
||||
liniile sterse la o editare anterioara. De aceea `ScrieArticoleFacturaEditate` ruleaza DUPA
|
||||
`finalizeaza_modificare_nota`, nu inauntrul ei: scrierea liniilor trebuie sa vina dupa acest reset,
|
||||
ca sa-l corecteze, nu inaintea lui.
|
||||
|
||||
`ScrieArticoleFacturaEditate` (`COMUN\programe\ofacturare_editare.prg:468-555`):
|
||||
1. marcheaza `sters = 1` pe tot documentul din `VANZARI_DETALII` (`:489-491`);
|
||||
2. invie si actualizeaza liniile pastrate din `tvd` (cantitate, pret, pret_cu_tva - `pret_achizitie`
|
||||
se omite, ramane valoarea persistata) (`:497-506`);
|
||||
3. insereaza liniile noi (`id_vanzare_det = 0`), fara `id_vanzare_det` explicit - il genereaza
|
||||
trigger-ul `TRG_VANZARI_DET_BEFOINS` (`:518-535`);
|
||||
4. apeleaza `pack_facturare.recalculeaza_totaluri_vanzari(id_vanzare, discount)` (`:544-548`), cu
|
||||
discountul luat din `tvanz.discount`; `NULL` pastreaza valoarea curenta din `VANZARI` in loc s-o
|
||||
zeroeze.
|
||||
|
||||
O linie stearsa de utilizator la o editare ramane stearsa si dupa reeditari ulterioare - fiecare
|
||||
salvare reface pasii 1-2 pe starea curenta din `tvd`, deci resetul din `actualizeaza_vanzari` e
|
||||
mereu corectat inainte sa ajunga vizibil.
|
||||
|
||||
`pack_facturare.recalculeaza_totaluri_vanzari` (script de migrare
|
||||
`ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql`) recalculeaza din `VANZARI_DETALII` - liniile proprii
|
||||
si, separat, liniile din seturi agregate din `VANZARI_SETURI` - coloanele `discount`,
|
||||
`discount_tva`, `valoare_achizitie`, `total_fara_tva`, `total_tva`, `total_cu_tva`, `valval`,
|
||||
`tvaval`, `totval`, `id_valuta`, `curs`, `multiplicator`, cu acelasi calcul per-linie ca la emitere
|
||||
(`calculeaza_total_fara_tva_fact`/`calculeaza_total_tva_fact`). Coloanele de incasare
|
||||
(`serie_incasat`/`nr_incasat`/`suma_incasat`/`tip_incasat`) nu sunt atinse.
|
||||
|
||||
View-ul `VVANZARI_ARTICOLE` (script de migrare `ff_2026_08_09_02_COMUN_VVANZARI_ARTICOLE.sql`)
|
||||
expune direct `VANZARI_DETALII`, cu `id_vanzare_set` si `pret_achizitie` printre coloanele proprii
|
||||
ale tabelei, plus denumire/codmat/nume_gestiune/nume_val din join-uri - sursa cursorului `tvd`.
|
||||
|
||||
### Editarea in grid
|
||||
|
||||
Gridul `pgfArticole.PAGE3.grdArticoleFactura` (`omodificari.vc2:12320-...`) e legat pe `tvd`. Linia
|
||||
provenita dintr-un set (`id_vanzare_set <> 0`) e needitabila (cantitate, pret, `pret_cu_tva`) si
|
||||
apare intr-o culoare distincta in grid (`DynamicForeColor`); coloana `pret_achizitie` e editabila
|
||||
doar pe liniile noi (`id_vanzare_set = 0 AND id_vanzare_det = 0`), doar-afisare pe restul
|
||||
(`:16526-16552`). Stergerea unei linii e logica - `cmdStergeArticol.Click` comuta `sters` pe randul
|
||||
curent din `tvd`, ramane vizibila grizata pana la salvare (`:16508-16517`). Adaugarea reutilizeaza
|
||||
dialogul `frm_articol_factura` de la compunerea facturii (`:16497-16505`).
|
||||
|
||||
Inainte de salvare (`inainte_de_do_termin`, `:14329-14386`, activa doar cand
|
||||
`ofacturare_editare.prg` e incarcat si `tvd` exista), pentru fiecare linie activa din `tvd`: opreste
|
||||
salvarea daca are cantitate <= 0, pret nul sau nu are articol asociat; cere confirmare daca o linie
|
||||
noua are pretul de achizitie 0, respectiv daca toate liniile facturii au fost sterse.
|
||||
|
||||
## Implicatii practice
|
||||
|
||||
- Codul (`cod`) unui document din Registrul Jurnal NU e stabil dupa modificare/anulare - se schimba
|
||||
la fiecare editare. Cod hardcodat sau retinut dintr-o executare anterioara devine invalid.
|
||||
- Regasirea documentului editat se face dupa `id_fact` (sau alt marcaj stabil), niciodata dupa `cod`.
|
||||
- Randurile `sters = 1` ramase in `ACT`/`RUL`/`RUL_OBINV` dupa o modificare sunt normale (istoric),
|
||||
nu date corupte sau duplicate de curatat.
|
||||
- Editarea unei facturi de vanzare (document cu rand in `VANZARI`) reface si liniile si totalurile
|
||||
denormalizate din `VANZARI`/`VANZARI_DETALII`, in aceeasi tranzactie cu nota - vezi ramura de mai
|
||||
sus.
|
||||
- Documentele care nu sunt facturi de vanzare nu sunt atinse de aceasta ramura - pagina de articole
|
||||
nu apare si scrierea in `VANZARI_DETALII` nu se declanseaza (garda: `Reccount('tvanz') = 1`).
|
||||
@@ -1,65 +1,88 @@
|
||||
# Flux SVN + git pentru COMUN
|
||||
|
||||
**SVN = șeful** (munca reală circulă prin el). **git = oglindă** pentru unelte (Claude, căutare).
|
||||
git primește de la SVN, niciodată invers.
|
||||
|
||||
## Reguli
|
||||
|
||||
1. **Munca reală se comite DOAR în SVN.** Nu face `git commit` cu o modificare nouă care n-a trecut prin SVN.
|
||||
2. **git se împrospătează DIN svn**, într-o singură direcție.
|
||||
3. **COMUN se publică pe git dintr-UN SINGUR folder** (publisher, ex. `ROAAUTO\COMUN`). Celelalte doar se aliniază la origin.
|
||||
|
||||
## Lucrat în paralel în 2 proiecte (ex. roagest + roaauto), fișiere diferite
|
||||
|
||||
### 1. Împaci în SVN
|
||||
```
|
||||
# ROAGEST\COMUN
|
||||
svn commit -m "modificari roagest"
|
||||
# ROAAUTO\COMUN
|
||||
svn update # aduce fisierele din roagest (alte fisiere -> fara conflict)
|
||||
svn commit -m "modificari roaauto"
|
||||
# ROAGEST\COMUN
|
||||
svn update # aduce fisierele din roaauto
|
||||
```
|
||||
Acum ambele copii SVN au tot. E sursa de adevăr.
|
||||
|
||||
### 2. Oglindești în git (doar din folderul publisher)
|
||||
```
|
||||
cd ROAAUTO\COMUN
|
||||
git add -A
|
||||
git commit -m "sync svn"
|
||||
git push
|
||||
```
|
||||
|
||||
### 3. Celălalt folder: aliniere, NU commit
|
||||
```
|
||||
cd ROAGEST\COMUN
|
||||
git fetch origin
|
||||
git reset --hard origin/main
|
||||
```
|
||||
Sigur: fișierele sunt deja identice cu origin (le-a făcut svn), `reset` doar mută pointerul.
|
||||
|
||||
## Când te muți dintr-un proiect în altul
|
||||
```
|
||||
svn update # in proiectul unde intri
|
||||
git reset --hard origin/main # in COMUN, ca git-ul sa fie curat
|
||||
```
|
||||
|
||||
## Regula care rezumă tot
|
||||
> Un singur folder publică în git (commit+push). Celelalte doar `git reset --hard origin/main`.
|
||||
> Munca circulă prin SVN; git fotografiază rezultatul.
|
||||
|
||||
## Model de branching (git urmareste text .??2)
|
||||
|
||||
git urmareste versiunile text FoxBin2Prg (.vc2/.sc2/…), improspatate in-arbore cu
|
||||
`git_sync.ps1` la inceput de sesiune si inainte de orice commit; nu comite cat timp
|
||||
`git_sync` raporteaza esecuri (exit nenul). Doua benzi:
|
||||
|
||||
- **`main` = oglinda SVN**: primeste DOAR commit-uri `sync SVN rN`, facute din stare curata
|
||||
(imediat dupa `svn update`, inainte de lucru local).
|
||||
- **Claude lucreaza pe branch** `claude/<subiect>` si comite doar acolo;
|
||||
`git diff main..claude/<subiect>` arata exact si numai munca lui.
|
||||
- Dupa ce modificarile intra in SVN (`svn commit` facut de utilizator), branch-ul se inchide
|
||||
(merge in `main` la urmatorul sync sau stergere).
|
||||
- Igiena: sync pe `main` doar din stare curata — `svn update` in mijlocul lucrului amesteca
|
||||
binarele pe disc.
|
||||
# COMUN: flux SVN + git
|
||||
|
||||
SVN = sursa de adevăr. git = oglindă. Pe `main` din COMUN scrie **doar** `roa_sync`.
|
||||
|
||||
De ce: `COMUN` e același repo git ținut în 8 copii, câte una per proiect. `main` are un singur
|
||||
furnizor — SVN, prin `roa_sync`. Conținut intrat pe altă ușă revine oricum ca `sync SVN rN` după
|
||||
`svn commit`: același conținut, alt SHA, conflict.
|
||||
|
||||
## Utilizatorul doar aprobă
|
||||
|
||||
Comenzile le rulezi **tu**: `roa_sync.bat`, `svn commit`, `roa_sync.bat`. El nu ține minte niciun
|
||||
pas și nu tastează nimic — dar **nimic nu se comite fără un „da" explicit de la el.**
|
||||
|
||||
Deci: nu te opri tăcut după ce livrezi diff-ul. **Întreabă**, cu fișierele și mesajul propuse.
|
||||
|
||||
## Flux
|
||||
|
||||
```
|
||||
.prg / .md / .ps1 / .sql .vc2 / .sc2
|
||||
│ │
|
||||
│ txt2vcx.ps1 <- IMEDIAT
|
||||
│ │
|
||||
│ verifica pe BINAR
|
||||
└────────────────┬────────────────┘
|
||||
│
|
||||
antet la zi + test rulat
|
||||
│
|
||||
diff ca fisier in docs\
|
||||
│
|
||||
INTREBI: fisiere + mesaj --> "da" ? --no--> stop
|
||||
│ da
|
||||
svn commit TINTIT (.prg | .scx + .sct -- niciodata .sc2)
|
||||
│
|
||||
roa_sync.bat --> main: sync SVN rN
|
||||
```
|
||||
|
||||
## Cazuri
|
||||
|
||||
**Intri în proiect** → rulezi `roa_sync.bat`, fără să întrebi, dacă `svn status` și `git status`
|
||||
sunt curate. Dacă nu sunt, întrebi întâi — pot fi modificări nefinalizate ale altcuiva.
|
||||
|
||||
**Ai editat `.prg` / `.md` / `.ps1` / `.sql`** → antetul la zi, testul rulat, diff-ul ca fișier în
|
||||
`docs\`.
|
||||
|
||||
**Ai editat `.vc2` / `.sc2`** → `txt2vcx.ps1` **imediat**, apoi verifici pe binar (reconvertești
|
||||
binarul într-un cache temporar și compari cu textul din arbore; mtime nu dovedește nimic). Text fără
|
||||
write-back = modificarea nu există. Abia apoi antet / test / diff.
|
||||
|
||||
**Vrei să-ți ții munca în git** → branch. În repo-ul proiectului: liber. În `COMUN`:
|
||||
`claude/<subiect>`, commit **doar** acolo, niciodată pe `main`.
|
||||
|
||||
**Ai terminat branch-ul** → în repo-ul proiectului: merge în `main`, normal. În `COMUN`: **nu face
|
||||
merge**. După `svn commit`, conținutul ajunge pe `main` ca `sync SVN rN`; branch-ul se șterge.
|
||||
|
||||
**Vrei `svn update`** → doar din stare curată. Niciodată în mijlocul lucrului: aduce binare noi peste
|
||||
ce ai pe disc. Dacă ai text `.??2` editat fără write-back, fă întâi write-back-ul.
|
||||
|
||||
**`svn update` a dat conflict** → oprește-te și raportează. Binarele nu se rezolvă manual.
|
||||
|
||||
**După `svn update`, git arată fișiere modificate** → e oglinda rămasă în urmă, nu munca ta.
|
||||
Nu le comite de mână; le ia `roa_sync` într-un `sync SVN rN`.
|
||||
|
||||
**Diff-ul e gata** → ceri aprobarea, explicit și complet: lista fișierelor de comis și mesajul
|
||||
propus. Nu presupune „da" din tăcere și nu amâna întrebarea pentru „mai târziu" — el nu ține minte
|
||||
pasul, tu îl ții.
|
||||
|
||||
**A zis „da"** → rulezi tu `svn commit` **țintit**, doar fișierele aprobate — pe binar
|
||||
(`.scx` + `.sct`), nu pe `.sc2`. Niciodată pe tot `COMUN`: intră zgomotul de compilare VFP.
|
||||
Imediat după, rulezi `roa_sync.bat`. Raportezi revizia SVN și ce a intrat pe `main`.
|
||||
|
||||
**A zis „nu" sau a cerut modificări** → nu comiți, nu insiști, nu rulezi `roa_sync`. Lucrarea rămâne
|
||||
necomisă pe disc și o raportezi ca atare la predarea contextului.
|
||||
|
||||
**Predai contextul** → raportează explicit dacă ai lăsat text `.??2` editat fără write-back. E stare
|
||||
periculoasă.
|
||||
|
||||
## Interzis
|
||||
|
||||
- `git commit` / `git push` / `git merge` pe `main` în `COMUN`
|
||||
- copierea unui fișier dintr-o copie de `COMUN` în alta — `svn update` îl duce; copierea = intrare dublă
|
||||
- write-back pe `.fr2` / `.mn2` / `.lb2` / `.pj2` — nu e suportat; acolo textul se citește, modificarea se face în IDE
|
||||
|
||||
## Copii rămase în urmă
|
||||
|
||||
Nimic nu se sincronizează în fundal. O copie neatinsă de luni se aliniază singură la primul
|
||||
`roa_sync.bat` rulat de acolo: `svn update` → regenerare text → `sync SVN rN` → fetch → ff sau
|
||||
`rebase --empty=drop`, care aruncă automat sync-urile al căror conținut e deja pe origin. De aceea
|
||||
regula veche „un singur folder publisher" e retrasă: numărul de copii nu mai contează.
|
||||
|
||||
@@ -1,48 +1,46 @@
|
||||
# Inrolarea unui proiect ROA (Visual FoxPro) in fluxul git-text FoxBin2Prg
|
||||
|
||||
Instructiuni pas cu pas pentru o sesiune Claude Code care inroleaza un proiect ROA
|
||||
in fluxul in care git urmareste DOAR versiunile text FoxBin2Prg (.vc2/.sc2/.fr2/.mn2/
|
||||
.lb2/.pj2/.dc2/.db2) generate in arbore, langa binarele VFP. SVN ramane sursa de
|
||||
adevar si nu se atinge (niciun svn commit fara acordul explicit al utilizatorului).
|
||||
Pasi pentru o sesiune Claude Code care inroleaza un proiect ROA in fluxul in care git urmareste
|
||||
DOAR versiunile text FoxBin2Prg (.vc2/.sc2/.fr2/.mn2/.lb2/.pj2/.dc2/.db2) generate in arbore,
|
||||
langa binarele VFP. SVN ramane sursa de adevar si nu se atinge (niciun svn commit fara acordul
|
||||
explicit al utilizatorului).
|
||||
|
||||
Proiecte deja inrolate (16.07.2026): ROACONT, ROAGEST, ROAAUTO, ROAIMOB, ROAACNPRO,
|
||||
ROAFACTURARE + COMUN (romfast/comun.git). Modelul de referinta este ROACONT.
|
||||
Proiecte deja inrolate: ROACONT, ROAGEST, ROAAUTO, ROAIMOB, ROAACNPRO, ROAFACTURARE + COMUN
|
||||
(romfast/comun.git). Modelul de referinta e ROACONT.
|
||||
|
||||
## Reguli pentru sesiunea care executa
|
||||
|
||||
- Foloseste EXCLUSIV PowerShell pentru comenzi (NU tool-ul Bash — bash.exe crapa pe
|
||||
aceste masini si lasa stackdump-uri).
|
||||
- NU face niciun `svn commit`. NU modifica binarele VFP. La final binarele trebuie sa
|
||||
fie byte-identice (verificabil cu `svn status`: niciun binar M).
|
||||
- Rularile de conversie dureaza zeci de minute pe proiecte mari: sunt incrementale,
|
||||
daca expira timeout-ul tool-ului se reiau pana la capat.
|
||||
- Foloseste EXCLUSIV PowerShell (NU Bash — bash.exe crapa pe aceste masini si lasa stackdump-uri).
|
||||
- NU face niciun `svn commit`. NU modifica binarele VFP. La final binarele trebuie sa fie
|
||||
byte-identice (`svn status`: niciun binar M).
|
||||
- Rularile de conversie dureaza zeci de minute pe proiecte mari: sunt incrementale, daca expira
|
||||
timeout-ul tool-ului se reiau pana la capat.
|
||||
- Nu rula doua conversii git_sync in paralel pe acelasi arbore.
|
||||
|
||||
## Preconditii
|
||||
|
||||
1. Tooling-ul partajat exista in `D:\ROA\UTIL\foxbin2prg\`: `git_sync.ps1`,
|
||||
`vfp_filemap.ps1`, `txt2vcx.ps1`, `test_git_sync.ps1`,
|
||||
`test_roundtrip.ps1`. Citeste-le inainte (macar help-ul din git_sync.ps1).
|
||||
`roa_sync.ps1` (+ `test_roa_sync.ps1`) traieste in `COMUN\scripts\` si vine
|
||||
singur cu svn update; in foxbin2prg a ramas doar un stub de compatibilitate.
|
||||
2. Proiectul e working copy SVN valid (`svn info D:\ROA\<PROIECT>`), cu `COMUN\`
|
||||
inauntru (external SVN).
|
||||
3. Repo-ul gitea exista: `git ls-remote git@gitea.romfast.ro:romfast/<proiect>.git`.
|
||||
Daca nu exista, cere utilizatorului sa-l creeze din interfata gitea (NU crea
|
||||
repo-uri prin API din proprie initiativa).
|
||||
4. SVN global-ignores pe masina contine `*.vc2 *.sc2 *.fr2 *.mn2 *.lb2 *.pj2 *.dc2
|
||||
*.db2 *.dbf.cfg` (in `%APPDATA%\Subversion\config`, sectiunea [miscellany]).
|
||||
Fara asta, textele apar ca `?` in svn status si risca svn add accidental.
|
||||
5. Daca proiectul ARE deja git cu istoric si urmeaza reset: confirmarea utilizatorului
|
||||
ca nu exista clone active pe alte masini (force-push rescrie istoria).
|
||||
1. Tooling partajat in `D:\ROA\UTIL\foxbin2prg\`: `git_sync.ps1`, `vfp_filemap.ps1`,
|
||||
`txt2vcx.ps1`, `test_git_sync.ps1`, `test_roundtrip.ps1`. Citeste-le inainte (macar help-ul
|
||||
din git_sync.ps1). `roa_sync.ps1` (+ `test_roa_sync.ps1`) traieste in `COMUN\scripts\` si
|
||||
vine singur cu svn update; in foxbin2prg a ramas doar un stub de compatibilitate.
|
||||
2. Proiectul e working copy SVN valid (`svn info D:\ROA\<PROIECT>`), cu `COMUN\` inauntru
|
||||
(external SVN).
|
||||
3. Repo-ul gitea exista: `git ls-remote git@gitea.romfast.ro:romfast/<proiect>.git`. Daca nu
|
||||
exista, cere utilizatorului sa-l creeze din interfata gitea (NU crea repo-uri prin API din
|
||||
proprie initiativa).
|
||||
4. SVN global-ignores pe masina contine `*.vc2 *.sc2 *.fr2 *.mn2 *.lb2 *.pj2 *.dc2 *.db2
|
||||
*.dbf.cfg` (in `%APPDATA%\Subversion\config`, sectiunea [miscellany]). Fara asta, textele apar
|
||||
ca `?` in svn status si risca svn add accidental.
|
||||
5. Daca proiectul ARE deja git cu istoric si urmeaza reset: confirmarea utilizatorului ca nu
|
||||
exista clone active pe alte masini (force-push rescrie istoria).
|
||||
|
||||
## Pasi
|
||||
|
||||
### 1. Inventar prealabil (inainte de orice stergere)
|
||||
|
||||
- Exista `.git`? Noteaza `git remote -v` si branch-ul. Exista `COMUN\.git`?
|
||||
- `git ls-files *.dbf` (daca exista repo vechi): tabelele urmarite azi ca binare sunt
|
||||
candidate la conversie .db2 (cerinta: tot ce e convertibil trece pe text).
|
||||
- `git ls-files *.dbf` (daca exista repo vechi): tabelele urmarite azi ca binare sunt candidate
|
||||
la conversie .db2 (cerinta: tot ce e convertibil trece pe text).
|
||||
|
||||
### 2. Conversia completa
|
||||
|
||||
@@ -50,25 +48,25 @@ ROAFACTURARE + COMUN (romfast/comun.git). Modelul de referinta este ROACONT.
|
||||
& D:\ROA\UTIL\foxbin2prg\git_sync.ps1 -ProjectRoot D:\ROA\<PROIECT>
|
||||
```
|
||||
|
||||
- DbfList implicit acopera `Locale\locale*.dbf`, `Help\*.dbf`, `DATE\Optiuni_*.dbf`
|
||||
si toate dbf-urile COMUN. Tabele de configurare specifice proiectului se adauga cu
|
||||
`-DbfList` explicit (ATENTIE: parametrii array NU se pot pasa prin
|
||||
`powershell -File` — invoca scriptul in-process cu `&`, altfel array-ul se
|
||||
colapseaza). Tabele operationale mari nu se adauga; un .db2 peste 5 MB ramane binar.
|
||||
- DbfList implicit acopera `Locale\locale*.dbf`, `Help\*.dbf`, `DATE\Optiuni_*.dbf` si toate
|
||||
dbf-urile COMUN. Tabele de configurare specifice proiectului se adauga cu `-DbfList` explicit
|
||||
(ATENTIE: parametrii array NU se pot pasa prin `powershell -File` — invoca scriptul in-process
|
||||
cu `&`, altfel array-ul se colapseaza). Tabele operationale mari nu se adauga; un .db2 peste
|
||||
5 MB ramane binar.
|
||||
- Esecuri de conversie — se investigheaza fiecare:
|
||||
- meniuri pre-VFP9 ("NOT in VFP 9 Format"): raman binare, cu exceptii negate `!` in
|
||||
.gitignore; intra in flux doar dupa re-salvare in VFP9 (MODIFY MENU -> save);
|
||||
- clase FFC/third-party cu roundtrip fals-negativ (#INCLUDE lipsa in staging izolat,
|
||||
ex. cele 6 din COMUN deja scutite implicit): se adauga la `-RoundtripExempt`;
|
||||
- clase FFC/third-party cu roundtrip fals-negativ (#INCLUDE lipsa in staging izolat, ex. cele
|
||||
6 din COMUN deja scutite implicit): se adauga la `-RoundtripExempt`;
|
||||
- alte esecuri reale: fisierul ramane binar urmarit (exceptie `!`) si se raporteaza.
|
||||
- Regula: nu se trece mai departe cu esecuri neexplicate (exit code nenul).
|
||||
|
||||
### 3. .gitignore si .gitattributes
|
||||
|
||||
- Copiaza `D:\ROA\ROACONT\.gitignore` ca model si adapteaza: sectiunea machine-local
|
||||
(exe-ul proiectului, <proiect>_ref.DBF/FPT/CDX, FOXUSER, .ini/.ARM, log-uri) si
|
||||
sectiunea dbf: fiecare .dbf care are .db2 se ignora INDIVIDUAL (plus .fpt-ul lui).
|
||||
NU ignora: `*.??2`, `*.dbf.cfg`, grafica (bmp/ico/jpg/png), ocx, tmpl.
|
||||
- Copiaza `D:\ROA\ROACONT\.gitignore` ca model si adapteaza: sectiunea machine-local (exe-ul
|
||||
proiectului, <proiect>_ref.DBF/FPT/CDX, FOXUSER, .ini/.ARM, log-uri) si sectiunea dbf: fiecare
|
||||
.dbf care are .db2 se ignora INDIVIDUAL (plus .fpt-ul lui). NU ignora: `*.??2`, `*.dbf.cfg`,
|
||||
grafica (bmp/ico/jpg/png), ocx, tmpl.
|
||||
- `.gitattributes` cu `* -text` (SVN ramane autoritatea EOL; git nu normalizeaza).
|
||||
|
||||
### 4. Init/reset repo proiect
|
||||
@@ -81,13 +79,12 @@ git -C D:\ROA\<PROIECT> add -A
|
||||
```
|
||||
|
||||
VERIFICARE OBLIGATORIE inainte de commit (`git ls-files` pe staged):
|
||||
- 0 binare convertibile urmarite (vcx/vct/scx/sct/frx/frt/mnx/mnt/lbx/lbt/pjx/pjt/
|
||||
dbc/dct/cdx/dcx), cu exceptia celor cu `!` justificate;
|
||||
- 0 binare convertibile urmarite (vcx/vct/scx/sct/frx/frt/mnx/mnt/lbx/lbt/pjx/pjt/dbc/dct/cdx/dcx),
|
||||
cu exceptia celor cu `!` justificate;
|
||||
- textele .??2 prezente; 0 fisiere din COMUN/ (are repo-ul lui).
|
||||
|
||||
Commit: `Initial: flux text FoxBin2Prg (git urmareste .??2 in-arbore, binarele VFP
|
||||
git-ignored)` + linia Co-Authored-By a sesiunii. Push: `git push -u origin main`
|
||||
(`--force` doar la reset).
|
||||
Commit: `Initial: flux text FoxBin2Prg (git urmareste .??2 in-arbore, binarele VFP git-ignored)`
|
||||
+ linia Co-Authored-By a sesiunii. Push: `git push -u origin main` (`--force` doar la reset).
|
||||
|
||||
### 5. Clona COMUN a proiectului
|
||||
|
||||
@@ -100,35 +97,34 @@ git -C D:\ROA\<PROIECT>\COMUN reset origin/main # mixed: pastreaza disc
|
||||
git -C D:\ROA\<PROIECT>\COMUN checkout origin/main -- .gitignore
|
||||
```
|
||||
|
||||
Diferentele ramase in `git status` = revizii SVN diferite ale clonei (normal).
|
||||
NU comite nimic in comun.git dintr-o clona decalata — comun se comite doar din clona
|
||||
in care s-a lucrat efectiv, dupa svn update.
|
||||
Diferentele ramase in `git status` = revizii SVN diferite ale clonei (normal). NU comite nimic in
|
||||
comun.git dintr-o clona decalata — comun se comite doar din clona in care s-a lucrat efectiv,
|
||||
dupa svn update.
|
||||
|
||||
### 6. roa_sync.bat
|
||||
|
||||
Copiaza `D:\ROA\ROAFACTURARE\roa_sync.bat` in radacina proiectului (e generic,
|
||||
foloseste `%~dp0` si cheama `COMUN\scripts\roa_sync.ps1`) si include-l in commit.
|
||||
Utilizatorul il ruleaza la inceput de sesiune: svn update -> git_sync -> commit
|
||||
"sync SVN rN" pe main (proiect + COMUN) -> reconciliere cu origin + push (doar
|
||||
commit-uri de sync) -> inchide branch-urile claude/* cu diff gol.
|
||||
Copiaza `D:\ROA\ROAFACTURARE\roa_sync.bat` in radacina proiectului (generic, foloseste `%~dp0` si
|
||||
cheama `COMUN\scripts\roa_sync.ps1`) si include-l in commit. Utilizatorul il ruleaza la inceput de
|
||||
sesiune: svn update -> git_sync -> commit "sync SVN rN" pe main (proiect + COMUN) -> reconciliere
|
||||
cu origin + push (doar commit-uri de sync) -> inchide branch-urile claude/* cu diff gol.
|
||||
|
||||
### 7. Verificari finale
|
||||
|
||||
- Acoperire: fiecare binar convertibil din arbore (inclusiv COMUN) are text .??2
|
||||
langa el (exceptiile `!` enumerate si justificate).
|
||||
- Acoperire: fiecare binar convertibil din arbore (inclusiv COMUN) are text .??2 langa el
|
||||
(exceptiile `!` enumerate si justificate).
|
||||
- `svn status`: niciun binar modificat, niciun .??2 adaugat in SVN.
|
||||
- `git ls-remote origin main` = HEAD-ul local.
|
||||
- Raport final: numar texte per tip, esecuri/scutiri, commit hash, push status.
|
||||
|
||||
## Note operationale
|
||||
|
||||
- Dialogurile modale FoxBin2Prg sunt suprimate de scripturi printr-un `foxbin2prg.cfg`
|
||||
cu `DontShowErrors: 1` scris per-director de staging (cfg-ul global de langa exe NU
|
||||
e fiabil). Daca utilizatorul vede totusi un MessageBox, e un dialog nativ VFP —
|
||||
watchdog-ul din Invoke-FoxBin2PrgSafe il omoara la timeout.
|
||||
- Dialogurile modale FoxBin2Prg sunt suprimate de scripturi printr-un `foxbin2prg.cfg` cu
|
||||
`DontShowErrors: 1` scris per-director de staging (cfg-ul global de langa exe NU e fiabil).
|
||||
Daca utilizatorul vede totusi un MessageBox, e un dialog nativ VFP — watchdog-ul din
|
||||
Invoke-FoxBin2PrgSafe il omoara la timeout.
|
||||
- Tabelele legate de un DBC au nevoie de .dbc/.dct/.dcx si .cdx langa ele la conversie
|
||||
(git_sync face asta automat in staging).
|
||||
- `DBF_Conversion_Support: 4` (scris de git_sync in cfg-ul de staging) exporta DATELE
|
||||
in .db2, nu doar structura.
|
||||
- Fisierele doar-git (docs, .bat, .gitignore) se comit separat, inainte de sync-ul
|
||||
"sync SVN rN", altfel nimeresc in commit-ul de sincronizare.
|
||||
- `DBF_Conversion_Support: 4` (scris de git_sync in cfg-ul de staging) exporta DATELE in .db2, nu
|
||||
doar structura.
|
||||
- Fisierele doar-git (docs, .bat, .gitignore) se comit separat, inainte de sync-ul "sync SVN rN",
|
||||
altfel nimeresc in commit-ul de sincronizare.
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# Inventar COMUN - functii/clase reutilizabile (ROAGEST)
|
||||
|
||||
Scop: referinta rapida pt. plan/code-review, ca sa refoloseasca comunele in loc sa se reinventeze
|
||||
(ex: Scan manual pt. lista dintr-un cursor, cand exista deja cursor2lista()). Generat prin grep pe
|
||||
COMUN/programe/*.prg + cache text D:\ROA\_vfp_textcache\roagest (nu presupuneri). Numerele = nr.
|
||||
aparitii grep in tot proiectul (indiciu de cat de "canonic" e functia).
|
||||
Scop: reutilizare comune la plan/code-review (ex. cursor2lista() in loc de Scan manual pe cursor).
|
||||
Generat prin grep pe COMUN/programe/*.prg + cache text D:\ROA\_vfp_textcache\roagest. Numerele =
|
||||
nr. aparitii grep in proiect (indiciu cat de "canonic" e functia).
|
||||
|
||||
## 1. Functii comune - COMUN\programe\oproceduri_comune.prg (clasa Oracle/executor + utilitare)
|
||||
|
||||
@@ -90,14 +89,14 @@ aparitii grep in tot proiectul (indiciu de cat de "canonic" e functia).
|
||||
| GetUserDocPath | - | folder documente utilizator curent | - |
|
||||
| aleg_document_pereche | (vezi ooperatii_comune) | vezi sectiune 2 | - |
|
||||
|
||||
Nota: multe din functiile de mai sus exista **dublat** in `proceduri_comune.prg` (varianta veche,
|
||||
Nota: multe functii de mai sus exista **dublat** in `proceduri_comune.prg` (varianta veche,
|
||||
non-obiect) - ex. NEW_ID, SAVE_GRID*, XMENU, cursor2lista*, lista2array/cursor, get_mask, Get_Version,
|
||||
Get_Hexa, format_msg, C_LUNA/cluna, get_trimestru/semestru, GETCALLSTACK, CloneObj/CopyProps,
|
||||
ceretitlu_rap. La duplicat castiga fisierul adaugat **cel mai recent** cu SET PROCEDURE ADDITIVE -
|
||||
in roagest.prg OPROCEDURI_COMUNE.PRG (linia 238) vine dupa proceduri_comune (linia 218), deci
|
||||
varianta activa e cea din `oproceduri_comune.prg`. Din varianta veche raman folosite doar 2 functii
|
||||
unice: `extrage_optiuni(cLista,nId)` (valoare dintr-o lista "id::val;id::val", 11 uz) si
|
||||
`myScatter(tcBlank)` (SCATTER generic in obiect, 3 uz); restul functiilor unice de acolo = moarte.
|
||||
ceretitlu_rap. La duplicat castiga fisierul incarcat **cel mai recent** cu SET PROCEDURE ADDITIVE -
|
||||
in roagest.prg OPROCEDURI_COMUNE.PRG (linia 238) vine dupa proceduri_comune (linia 218), deci activa
|
||||
e varianta din `oproceduri_comune.prg`. Unice din varianta veche: `extrage_optiuni(cLista,nId)`
|
||||
(valoare din lista "id::val;id::val", 11 uz), `myScatter(tcBlank)` (SCATTER generic in obiect, 3 uz);
|
||||
restul functiilor unice de acolo = moarte.
|
||||
|
||||
## 2. Functii comune - COMUN\programe\ooperatii_comune.prg (contabilitate/analitice/balanta)
|
||||
|
||||
@@ -142,12 +141,12 @@ Preview rapoarte: FoxyPreviewer (`gcReportPreviewer = "FoxyPreview"` in roagest.
|
||||
| PreviewerConfig (clasa) | SetValue/GetValue | property-bag optiuni FoxyPreviewer (param toPreviewerConfig la export2frx) | - |
|
||||
|
||||
### Export Excel - 3 mecanisme paralele (atentie la confuzii)
|
||||
1. `goExport.export2xls/export2xlsx` (mai sus) - preferat pt. cod nou (export2xlsx).
|
||||
1. `goExport.export2xls/export2xlsx` (mai sus) - preferat pt. cod nou.
|
||||
2. `export_excel` / `export_excel_grid` / `exportare` / `LIST_EXCEL` (proceduri_excel.prg) - OLE
|
||||
Automation, scrie celula cu celula, necesita Excel instalat; uz mic (2-12). `get_excel_mask` de
|
||||
acolo = conversie masca VFP -> format Excel (nu confunda cu `get_mask` din sect. 1).
|
||||
Automation celula-cu-celula, cere Excel instalat; uz mic (2-12). `get_excel_mask` acolo =
|
||||
masca VFP -> format Excel (nu confunda cu `get_mask` din sect. 1).
|
||||
3. Clasa `excelxml` (excelxml.vcx, COMUN\UTILE\excel) - Excel XML direct din `gridobject`, fara
|
||||
Excel instalat (proprietati: file, sheetname, openaftersaving; metoda `save`); 73 uz.
|
||||
Excel instalat (proprietati file/sheetname/openaftersaving, metoda `save`); 73 uz.
|
||||
Plus functiile libere `export_xls`/`ExportToXMLExcel` din oproceduri_comune.prg (sect. 1) - cod
|
||||
diferit de metoda `goExport.export_xls`, doar nume identic.
|
||||
|
||||
@@ -288,28 +287,28 @@ Proprietate cheie comuna: `pcobj` (leaga containerul de camp/proprietate din obi
|
||||
|
||||
## 7. Ce am lasat pe dinafara (intentionat)
|
||||
|
||||
- `proceduri_comune.prg` (varianta veche) - acoperita acum in nota de la sect. 1 (2 functii unice
|
||||
folosite, restul dublate sau moarte); functiile ei unice cu 0 aparitii (caut_nume_politica,
|
||||
- `proceduri_comune.prg` (varianta veche) - acoperita in nota sect. 1 (2 functii unice folosite,
|
||||
restul dublate/moarte); functiile ei unice cu 0 aparitii (caut_nume_politica,
|
||||
make_sectii_utilizator, recompune_optiuni, cere*/compara*, debug_*_eventtracking, ...) - omise.
|
||||
- `oproceduri_comune_imob.prg` - varianta specifica ROAIMOB, nu ROAGEST.
|
||||
- `xdate.prg` - script procedural (incarca cursoarele xsets/xrequest/xnote la DO), nu expune functii.
|
||||
- Metoda `getUserRepPath` din oExportConfig - complet comentata (moarta); varianta activa e functia
|
||||
libera omonima din `proceduri_rapoarte.prg` (cod diferit).
|
||||
- Clase de nomenclatoare mari (`onomenclatoare.vcx`, `onom_articole.vcx`, `stocuri.vcx`, `rulaje.vcx`,
|
||||
`ointroduceri*.vcx`, `oinventar.vcx`) - business logic specific gestiune, prea voluminos pt. acest
|
||||
inventar (candidat pt. un inventar separat, per-flux, daca devine necesar).
|
||||
`ointroduceri*.vcx`, `oinventar.vcx`) - business logic gestiune, prea voluminos pt. acest inventar
|
||||
(candidat pt. inventar separat per-flux, daca devine necesar).
|
||||
- Clasele de configurare/serii (`configurare.vcx`, `serii_numere.vcx`, `ferestre_oracle.vcx`,
|
||||
`bon_fisc.vcx`) si utilitarele (`GridExtras`, `ctl32`, `hpdf`) - neinventariate, uz mai rar
|
||||
in fluxurile curente de lucru (`excelxml.vcx` e acoperita la sect. 3).
|
||||
- Functiile din `COMUN\programe` fara nicio aparitie gasita prin grep in ROAGEST (posibil folosite
|
||||
doar de alte aplicatii ROA) - omise.
|
||||
`bon_fisc.vcx`) si utilitarele (`GridExtras`, `ctl32`, `hpdf`) - neinventariate, uz rar in
|
||||
fluxurile curente (`excelxml.vcx` e acoperita la sect. 3).
|
||||
- Functiile din `COMUN\programe` fara nicio aparitie prin grep in ROAGEST (posibil doar alte
|
||||
aplicatii ROA) - omise.
|
||||
|
||||
## 8. Cum se foloseste
|
||||
|
||||
- **La plan**: inainte de a scrie cod/obiecte noi, scaneaza acest fisier + un grep tintit
|
||||
- **La plan**: inainte de cod/obiecte noi, scaneaza acest fisier + un grep tintit
|
||||
(`grep -rn "<nume_functie_candidata>" COMUN/programe D:\ROA\_vfp_textcache\roagest`) ca sa
|
||||
confirmi ca nu exista deja o comuna echivalenta.
|
||||
- **La code-review**: daca un diff introduce Scan manual pt. liste, MESSAGEBOX direct, SQLEXEC direct,
|
||||
un buton cu Click suprascris in loc de `caction`, un export Excel/listare construite manual in loc
|
||||
de `goExport.export2*`/FoxyPreview, sau un dialog de alegere nomenclator facut din SELECT+grid in
|
||||
loc de `caut_*` (ocautare.prg), semnaleaza reutilizarea comunei corespunzatoare din tabelele de mai sus.
|
||||
- **La code-review**: daca un diff introduce Scan manual pt. liste, MESSAGEBOX direct, SQLEXEC
|
||||
direct, un buton cu Click suprascris in loc de `caction`, export Excel/listare construite manual
|
||||
in loc de `goExport.export2*`/FoxyPreview, sau un dialog de alegere nomenclator din SELECT+grid
|
||||
in loc de `caut_*` (ocautare.prg), semnaleaza comuna corespunzatoare din tabelele de mai sus.
|
||||
|
||||
42
docs/monitorizare-context.md
Normal file
42
docs/monitorizare-context.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Hook-uri de disciplina (regulile 9 si 12)
|
||||
|
||||
## Monitorizare context sesiune (regula 9)
|
||||
|
||||
Agentul nu-si vede singur consumul de context. `COMUN\utile\context_watch.ps1` il citeste din
|
||||
transcriptul sesiunii (ultimul `usage`: `input_tokens + cache_read + cache_creation`) si avertizeaza
|
||||
peste prag: 250k = pregateste predarea, 275k = handoff acum.
|
||||
|
||||
Instalare, o data per calculator, in `%USERPROFILE%\.claude\settings.json` (nivel utilizator, prinde
|
||||
toate proiectele):
|
||||
|
||||
```json
|
||||
"hooks": {
|
||||
"UserPromptSubmit": [
|
||||
{ "hooks": [ { "type": "command",
|
||||
"command": "powershell -NoProfile -ExecutionPolicy Bypass -File \"D:\\ROA\\ROAGEST\\COMUN\\utile\\context_watch.ps1\" -Stdout" } ] }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- Ruleaza la fiecare mesaj al utilizatorului (~1s); sub prag nu scrie nimic.
|
||||
- `-Stdout` e obligatoriu pe `UserPromptSubmit` (mesajul intra in context, exit 0). Fara el scrie pe
|
||||
stderr si iese cu 2 - forma pentru `PostToolUse`.
|
||||
- Praguri configurabile: `-Prag`, `-PragMax`.
|
||||
- Verificare manuala: `powershell -File ...\context_watch.ps1 -Prag 900000 -PragMax 950000 -Intotdeauna`
|
||||
(afiseaza `CONTEXT <n>k` indiferent de prag).
|
||||
|
||||
## Revizuire periodica a docs (regula 12)
|
||||
|
||||
`COMUN\utile\docs_revizie_check.ps1` compara data din markerul `COMUN\docs\.ultima_revizie` cu ziua
|
||||
curenta si, peste 30 de zile, cere o runda de compactare. Se pune ca hook `SessionStart`, in acelasi
|
||||
`settings.json`, cu `-Stdout`:
|
||||
|
||||
```json
|
||||
"SessionStart": [
|
||||
{ "hooks": [ { "type": "command",
|
||||
"command": "powershell -NoProfile -ExecutionPolicy Bypass -File \"D:\\ROA\\ROAGEST\\COMUN\\utile\\docs_revizie_check.ps1\" -Stdout" } ] }
|
||||
]
|
||||
```
|
||||
|
||||
Dupa o revizie aplicata: `powershell -File ...\docs_revizie_check.ps1 -Marcheaza` (rescrie markerul).
|
||||
Interval configurabil cu `-Zile`.
|
||||
@@ -1,61 +1,78 @@
|
||||
# Export surse Oracle (PACK_CONTAFIN & co.) — cum se face
|
||||
|
||||
`PACK_CONTAFIN.pck` din acest folder este exportul sursei pachetului PL/SQL `PACK_CONTAFIN`.
|
||||
**Claude Code își face singur exportul/reîmprospătarea** — nu mai e nevoie de export manual din
|
||||
PL/SQL Developer.
|
||||
|
||||
## Conexiune
|
||||
|
||||
- Client: `D:\ROA\instantclient_19_18\sqlplus.exe` (`TNS_ADMIN` e deja setat spre același folder).
|
||||
- Alias TNS: `ROA_CENTRAL` → `10.0.20.121:1521`, `SERVICE_NAME=ROA` (vezi `tnsnames.ora`).
|
||||
- Schema/utilizator: `MARIUSM_AUTO` (schema de dezvoltare a lui Marius).
|
||||
- **Parola nu e versionată** — se află local, în `D:\ROA\ROAGEST\docs\local\oracle.md`
|
||||
(folder ignorat de git), pe mașina de lucru.
|
||||
|
||||
`PACK_CONTAFIN` există în schemele `MARIUSM_AUTO` (dev) și `ACN`, plus un sinonim `PUBLIC`.
|
||||
Exportul de referință se face din `MARIUSM_AUTO`.
|
||||
|
||||
## Gotcha sqlplus pe Windows/PowerShell
|
||||
|
||||
Nu trimite SQL prin pipe din PowerShell (`'select...' | sqlplus`) — BOM-ul UTF-16 sparge parserul
|
||||
(`SP2-0734: unknown command beginning "select..."`). Scrie un fișier `.sql` cu encoding **ASCII**
|
||||
și rulează-l cu `@fisier.sql`.
|
||||
|
||||
## Comanda de export (re-generare .pck)
|
||||
|
||||
```sql
|
||||
-- export_pack.sql
|
||||
set pagesize 0 linesize 400 trimspool on feedback off heading off termout off
|
||||
spool D:\ROA\ROAGEST\COMUN\docs\PACK_CONTAFIN.pck
|
||||
select text from all_source where owner='MARIUSM_AUTO' and name='PACK_CONTAFIN' and type='PACKAGE' order by line;
|
||||
select '/' from dual;
|
||||
select text from all_source where owner='MARIUSM_AUTO' and name='PACK_CONTAFIN' and type='PACKAGE BODY' order by line;
|
||||
select '/' from dual;
|
||||
spool off
|
||||
exit
|
||||
```
|
||||
|
||||
```powershell
|
||||
& 'D:\ROA\instantclient_19_18\sqlplus.exe' -L -S 'MARIUSM_AUTO/<parola>@ROA_CENTRAL' '@export_pack.sql'
|
||||
```
|
||||
|
||||
Același tipar merge pentru orice alt pachet/procedură (`PACK_SESIUNE`, `PACK_PRETURI`, …) sau pentru
|
||||
DDL de tabele/view-uri (`all_tab_columns`, `dbms_metadata.get_ddl`).
|
||||
|
||||
## Ce e strict necesar de știut despre PACK_CONTAFIN
|
||||
|
||||
Pachetul central de **scriere a documentelor** — clientul VFP populează tabelele temporare
|
||||
`ACT_TEMP`/`RUL_TEMP` (prin `oscrie_in_fisiere`-ul din COMUN), apoi pachetul distribuie:
|
||||
|
||||
- `SCRIE_IN_FISIERE` — orchestratorul (apelat per document).
|
||||
- `SCRIE_IN_ACT` — `ACT_TEMP` → `ACT` (notele contabile).
|
||||
- `SCRIE_IN_RUL` — `RUL_TEMP` → `RUL` (mișcările de stoc); completează `COD`, `DATAORA`, `ID_FACT`
|
||||
(min. `id_fact` fără conturi 5xx), `ID_SUCURSALA`, `DATAIN`/`DATAOUT` din `dataact`, opțional
|
||||
`ID_RUL_AUX` pe furnizor (opțiunea de firmă `RULAJFURNIZOR`). **Scrie exact ce e în RUL_TEMP — nu
|
||||
derivă rulaje din ACT**, deci filtrarea liniilor de rulaj se face în clientul VFP.
|
||||
- `SCRIE_IN_RUL_OBINV` / `SCRIE_IN_STOC` / `SCRIE_IN_STOC_OBINV` — variantele pentru obiecte de
|
||||
inventar și actualizarea stocului.
|
||||
- `VERIFICA_NOTE_CONTABILE`, `SCRIE_JC_2007`/`SCRIE_JV_2007` (jurnale TVA),
|
||||
`SCRIE_IN_BALANTA(_PARTENERI)`, `sterge_document`, `finalizeaza_document_*`.
|
||||
- Stare de sesiune prin settere/gettere (`SET_COD`/`GET_COD`, `SET_IDFACT`, `SET_ID_SUCURSALA`, …)
|
||||
+ `PACK_SESIUNE` (an/lună, opțiuni firmă).
|
||||
# Export surse Oracle (PACK_CONTAFIN & co.) — cum se face
|
||||
|
||||
`PACK_CONTAFIN.pck` din acest folder este exportul sursei pachetului PL/SQL `PACK_CONTAFIN`.
|
||||
Claude Code își face singur exportul/reîmprospătarea — nu mai e nevoie de export manual din
|
||||
PL/SQL Developer.
|
||||
|
||||
## Conexiune
|
||||
|
||||
- Client: `D:\ROA\instantclient_19_18\sqlplus.exe` (`TNS_ADMIN` deja setat spre același folder).
|
||||
- Alias TNS: `ROA_CENTRAL` → `10.0.20.121:1521`, `SERVICE_NAME=ROA` (vezi `tnsnames.ora`).
|
||||
- Schema/utilizator: `MARIUSM_AUTO` (schema de dezvoltare a lui Marius).
|
||||
- **Schema de lucru pentru verificari: `MARIUSM_AUTO` pe `ROA_CENTRAL`** - nu `ACN` sau altele.
|
||||
- **Parola nu e versionată în git** — în `COMUN\docs\local\oracle.md` (ignorat de git, există în SVN).
|
||||
|
||||
`PACK_CONTAFIN` există în schemele `MARIUSM_AUTO` (dev) și `ACN`, plus sinonim `PUBLIC`.
|
||||
Exportul de referință se face din `MARIUSM_AUTO`.
|
||||
|
||||
Înainte de a lua o sursă de acolo ca referință pentru o modificare, verifică că `MARIUSM_AUTO` are
|
||||
toate scripturile aplicate — procedura e în `scripturi-migrare-db.md`, secțiunea
|
||||
"Sursa de referință pentru DDL".
|
||||
|
||||
## Gotcha sqlplus pe Windows/PowerShell
|
||||
|
||||
Nu trimite SQL prin pipe din PowerShell (`'select...' | sqlplus`) — BOM-ul UTF-16 sparge parserul
|
||||
(`SP2-0734: unknown command beginning "select..."`). Scrie un fișier `.sql` cu encoding **ASCII**
|
||||
și rulează-l cu `@fisier.sql`.
|
||||
|
||||
## Comanda de export (re-generare .pck)
|
||||
|
||||
> **`linesize` prea mic corupe tăcut sursa.** SQL\*Plus face **wrap** la coloana `linesize`, deci o
|
||||
> linie de cod mai lungă e ruptă în două — inclusiv **prin mijlocul unui identificator**. Fișierul
|
||||
> pare întreg, `diff` față de el nu arată nimic, dar recompilarea lui dă erori la linii care n-au
|
||||
> nicio legătură cu ce ai modificat (`ORA-00920`, `PLS-*`). `PACK_FACTURARE` are linii de peste
|
||||
> **1000** de caractere, iar un export la `linesize 400` i-a rupt 8. Folosește `linesize 32767` și
|
||||
> verifică după export că nicio linie nu atinge exact valoarea `linesize`.
|
||||
>
|
||||
> **Exportul e bun pentru CITIT, nu ca bază pentru un script de migrare.** Pentru un script de
|
||||
> pachet, pleacă de la ultimul script aplicat din `SCRIPTURI_CLAR` (fișier real, care n-a trecut
|
||||
> niciodată printr-un spool) și confirmă că e la zi comparându-l cu exportul **ignorând spațiul
|
||||
> alb** — așa wrap-ul nu mai contează:
|
||||
> `tr -d ' \t\r\n' < fisier | md5sum` pe ambele.
|
||||
|
||||
```sql
|
||||
-- export_pack.sql
|
||||
set pagesize 0 linesize 32767 long 2000000 longchunksize 32767 trimspool on feedback off heading off termout off
|
||||
spool D:\ROA\ROAGEST\COMUN\docs\PACK_CONTAFIN.pck
|
||||
select text from all_source where owner='MARIUSM_AUTO' and name='PACK_CONTAFIN' and type='PACKAGE' order by line;
|
||||
select '/' from dual;
|
||||
select text from all_source where owner='MARIUSM_AUTO' and name='PACK_CONTAFIN' and type='PACKAGE BODY' order by line;
|
||||
select '/' from dual;
|
||||
spool off
|
||||
exit
|
||||
```
|
||||
|
||||
```powershell
|
||||
& 'D:\ROA\instantclient_19_18\sqlplus.exe' -L -S 'MARIUSM_AUTO/<parola>@ROA_CENTRAL' '@export_pack.sql'
|
||||
```
|
||||
|
||||
Același tipar merge pentru orice alt pachet/procedură (`PACK_SESIUNE`, `PACK_PRETURI`, …) sau
|
||||
pentru DDL de tabele/view-uri (`all_tab_columns`, `dbms_metadata.get_ddl`).
|
||||
|
||||
## Ce e strict necesar de știut despre PACK_CONTAFIN
|
||||
|
||||
Pachetul central de **scriere a documentelor** — clientul VFP populează tabelele temporare
|
||||
`ACT_TEMP`/`RUL_TEMP` (prin `oscrie_in_fisiere`-ul din COMUN), apoi pachetul distribuie:
|
||||
|
||||
- `SCRIE_IN_FISIERE` — orchestratorul (apelat per document).
|
||||
- `SCRIE_IN_ACT` — `ACT_TEMP` → `ACT` (notele contabile).
|
||||
- `SCRIE_IN_RUL` — `RUL_TEMP` → `RUL` (mișcările de stoc); completează `COD`, `DATAORA`, `ID_FACT`
|
||||
(min. `id_fact` fără conturi 5xx), `ID_SUCURSALA`, `DATAIN`/`DATAOUT` din `dataact`, opțional
|
||||
`ID_RUL_AUX` pe furnizor (opțiunea de firmă `RULAJFURNIZOR`). **Scrie exact ce e în RUL_TEMP — nu
|
||||
derivă rulaje din ACT**, deci filtrarea liniilor de rulaj se face în clientul VFP.
|
||||
- `SCRIE_IN_RUL_OBINV` / `SCRIE_IN_STOC` / `SCRIE_IN_STOC_OBINV` — variantele pentru obiecte de
|
||||
inventar și actualizarea stocului.
|
||||
- `VERIFICA_NOTE_CONTABILE`, `SCRIE_JC_2007`/`SCRIE_JV_2007` (jurnale TVA),
|
||||
`SCRIE_IN_BALANTA(_PARTENERI)`, `sterge_document`, `finalizeaza_document_*`.
|
||||
- Stare de sesiune prin settere/gettere (`SET_COD`/`GET_COD`, `SET_IDFACT`, `SET_ID_SUCURSALA`, …)
|
||||
+ `PACK_SESIUNE` (an/lună, opțiuni firmă).
|
||||
|
||||
@@ -1,8 +1,47 @@
|
||||
# Orchestrare cu subagenti: context mic, misiuni descompuse
|
||||
|
||||
Regula (valabila in toate proiectele ROA/VFP): un singur subagent care duce o misiune lunga
|
||||
(iteratii de teste, investigatii, mai multe sarcini inlantuite) acumuleaza context urias
|
||||
(s-a ajuns la ~800k tokens) — calitate degradata, cost mare. Nu se lucreaza asa.
|
||||
(iteratii de teste, investigatii, mai multe sarcini inlantuite) acumuleaza context urias —
|
||||
calitate degradata, cost mare. Nu se lucreaza asa.
|
||||
|
||||
## REGULA ZERO: predarea contextului e OBLIGATORIE, nu optionala
|
||||
|
||||
Se aplica **identic sesiunii principale si oricarui subagent**. Nu e o recomandare de eficienta,
|
||||
e o conditie de corectitudine: un context supraincarcat pierde tacut decizii deja luate si reia
|
||||
investigatii deja platite.
|
||||
|
||||
**Declansatoare — la oricare dintre ele, predarea porneste imediat:**
|
||||
|
||||
1. contextul propriu a trecut de **~50% din fereastra** (orchestrator) sau de **~200-250k tokens**
|
||||
(subagent);
|
||||
2. harness-ul anunta compactare automata (`PreCompact`) — **prea tarziu ca sa mai amani, dar nu
|
||||
prea tarziu ca sa scrii fisierul**; scrie handoff-ul inainte sa raspunzi orice altceva;
|
||||
3. utilizatorul semnaleaza ca s-a atins limita;
|
||||
4. s-a terminat un bloc de lucru — indiferent cat context a mai ramas.
|
||||
|
||||
**Procedura, in ordine, fara exceptii:**
|
||||
|
||||
1. **Opreste lucrul.** Nu incepe o sarcina noua, nu porni o rulare noua. Daca esti in mijlocul unei
|
||||
editari, du-o pana la o stare **consistenta pe disc** (text si binare sincronizate) si atat.
|
||||
2. **Scrie handoff-ul pe disc** (`docs\handoff_<subiect>.md`). Nu in mesaj, nu in raport — **pe
|
||||
disc**. Un mesaj catre orchestrator se pierde; fisierul nu.
|
||||
3. **Confirma in doua randuri** ce ai lasat in urma si daca ceva e intr-o stare periculoasa
|
||||
(fisier editat fara write-back, tranzactie deschisa, proces ramas viu, date de test consumate).
|
||||
4. **Opreste-te.** Blocul urmator il ia un agent proaspat. "Mai am putin" nu e motiv de amanare —
|
||||
exact acolo se pierd lucrurile.
|
||||
|
||||
**Obligatia e a fiecaruia, nu doar a orchestratorului.** Un subagent care simte ca se apropie de
|
||||
prag **anunta singur** si cere predarea; nu asteapta sa fie oprit. Un orchestrator care se apropie
|
||||
de prag isi scrie propriul handoff si preda orchestrarea unei sesiuni noi — regula nu are portita
|
||||
pentru "eu doar coordonez".
|
||||
|
||||
**Ce intra obligatoriu in handoff**: inventarul livrabilelor cu `fisier:linie`; ce e terminat si ce
|
||||
nu; **daca write-back-ul e facut** pentru fiecare fisier atins; comanda exacta de rulare a testelor
|
||||
si unde scriu logurile; ce s-a stabilit deja (ca sa nu se reia); ce e interzis; starea datelor de
|
||||
test consumate; capcanele de mediu platite. Fara analize noi — doar stare.
|
||||
|
||||
Doua lectii platite scump, amandoua din aceeasi cauza — un agent tinut peste prag (`s5-nivel2`
|
||||
533k, `s2d-modifica-gestiuni` 434k). Predarea e aproape gratuita: raportul e oricum deja scris.
|
||||
|
||||
## Cum se lucreaza
|
||||
|
||||
@@ -38,3 +77,64 @@ Regula (valabila in toate proiectele ROA/VFP): un singur subagent care duce o mi
|
||||
completeaza-l, nu repeta investigatia.
|
||||
- Orchestratorul face el insusi munca de volum -> deleaga si pastreaza-si contextul
|
||||
pentru decizii, verificari si deblocari.
|
||||
|
||||
## Disciplina de context a ORCHESTRATORULUI
|
||||
|
||||
Pragul de ~200-250k e pentru subagenti, dar orchestratorul se umple la fel de repede daca isi
|
||||
lasa in sesiune munca de CITIT (masurat: o runda de implementare + 4 rulari de teste a dus
|
||||
sesiunea principala la ~570k desi tot codul fusese scris de subagenti). Principalii consumatori:
|
||||
citirea rezultatelor de test dupa fiecare rulare (cu tot cu liniile "OK"), citirea codului pentru
|
||||
diagnostic, fixuri aplicate direct in loc de delegate.
|
||||
|
||||
- **Nu citi log-uri brute.** Scripturile de raportare afiseaza DOAR esecurile plus un total
|
||||
("22 OK, 3 FAIL: <nume + linia de esec>"). Tabelul complet se citeste o singura data, la
|
||||
baseline - nu dupa fiecare rulare. Pentru suitele VFP exista deja:
|
||||
`COMUN\utile\Teste\raport_teste.ps1 -Dir <folder> [-Tot] [-Baseline <fisier>]` - fara `-Tot`
|
||||
afiseaza doar esecurile, iar cu `-Baseline` le marcheaza `[preexistent]` vs `[NOU - REGRESIE]`.
|
||||
- **Nu citi cod ca sa diagnostichezi.** Deleaga cu "adu-mi dovada, nu fisierul": agentul intoarce
|
||||
cauza + linia + citatul minim. Verifici afirmatia, nu o redescoperi.
|
||||
- **Verifica prin assert, nu prin citire.** Daca vrei sa stii ca ceva e adevarat, cere o comanda
|
||||
care intoarce da/nu, nu continutul din care ai deduce singur.
|
||||
- **Nu aplica fixuri direct** decat sub ~5 linii si doar daca ai deja contextul in sesiune.
|
||||
- **Prag si pe orchestrator**: la ~50% din fereastra, scrie handoff-ul si reia orchestrarea
|
||||
dintr-o sesiune noua. Handoff-ul e deja pe disc - exact pentru asta exista. Vezi **Regula zero**
|
||||
de la inceputul fisierului: obligatia e aceeasi ca pentru subagenti, fara portita pentru
|
||||
"eu doar coordonez".
|
||||
|
||||
## Model de lucru: backlog de story-uri mici, context mic per story
|
||||
|
||||
Impartirea pe "lane-uri" mari (o clasa, un modul) produce subagenti cu context mare si serializare
|
||||
pe fisier. Alternativa mai ieftina si mai robusta: **backlog de story-uri mici, fiecare rezolvabila
|
||||
cu context mic, rulate in bucla de agenti PROASPETI.**
|
||||
|
||||
Doua fisiere pe disc tin toata starea:
|
||||
|
||||
- `docs/handoff_<subiect>.md` - **contextul stabil**: reguli de editare, cai, ancore verificate,
|
||||
capcane confirmate, decizii luate. Il citeste fiecare agent; se actualizeaza rar.
|
||||
- `docs/backlog_<subiect>.md` - **starea vie**: story-uri cu ID, criteriu de acceptare
|
||||
VERIFICABIL, fisiere atinse, stare (`todo` / `in lucru` / `gata` / `blocat de #N`).
|
||||
|
||||
Bucla:
|
||||
1. orchestratorul ia primul story `todo` neblocat;
|
||||
2. spawneaza un agent proaspat cu prompt = trimitere la handoff + textul story-ului + criteriul
|
||||
de acceptare. **Nimic altceva** - fara istoric, fara rapoartele celorlalti agenti;
|
||||
3. agentul modifica, ruleaza verificarea din criteriu si raporteaza **verdict + ce a schimbat +
|
||||
ce a descoperit neasteptat**, atat;
|
||||
4. orchestratorul marcheaza story-ul in backlog si trece la urmatorul.
|
||||
|
||||
O story buna: are criteriu de acceptare care se poate RULA (un test, un grep, o comanda da/nu);
|
||||
atinge un singur fisier sau o singura zona (altfel story-urile se serializeaza intre ele); incape
|
||||
in 15-20 de linii de descriere; nu cere citirea intregului fisier ca sa fie inteleasa.
|
||||
|
||||
Sablon:
|
||||
|
||||
### S7 - garda pe randul protejat in recalcule
|
||||
Fisiere: COMUN\clase\<x>.vc2 (do_executa, recalc_tva_document)
|
||||
Blocat de: S4
|
||||
De facut: <2-4 propozitii>
|
||||
Acceptare: test_<y>.ps1 trece 12/12 SI `rand_protejat()` nu mai apare in nicio clauza Where
|
||||
Stare: todo
|
||||
|
||||
Cand un story pica de doua ori la rand, nu-l reincerca a treia oara cu acelasi prompt: semnul e ca
|
||||
descrierea sau criteriul e gresit, nu executia. Rescrie story-ul (mai mic, sau cu criteriul
|
||||
corectat) inainte de a mai cheltui un agent.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Prompt: seteaza conventia docs/ (insight-uri de proiect) intr-un proiect ROA
|
||||
|
||||
Template partajat intre proiectele ROA* (similar cu `changelog_template.txt`). Origine: ROAIMOB, 08/07/2026. Copiaza blocul de mai jos (adaptat, daca e nevoie) intr-o sesiune Claude Code din radacina oricarui proiect ROA* pentru a initializa aceeasi conventie.
|
||||
Template partajat intre proiectele ROA* (similar cu `changelog_template.txt`). Copiaza blocul de mai jos (adaptat, daca e nevoie) intr-o sesiune Claude Code din radacina oricarui proiect ROA* pentru a initializa aceeasi conventie.
|
||||
|
||||
---
|
||||
|
||||
|
||||
83
docs/publicare-scripturi-db.md
Normal file
83
docs/publicare-scripturi-db.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# Publicarea scripturilor de baza de date catre clienti
|
||||
|
||||
Scriptul: `COMUN\utile\publicare_scripturi.ps1`. Inlocuieste pasii manuali din `tasks.exe`
|
||||
(`D:\PROIECTE\fox\tasks`, formularul din `clase\generare_script.vcx`), care raman varianta de rezerva.
|
||||
Cum se scrie un script de migrare: `scripturi-migrare-db.md`.
|
||||
|
||||
```powershell
|
||||
powershell -File COMUN\utile\publicare_scripturi.ps1 -DryRun # ce ar face pe luna curenta
|
||||
powershell -File COMUN\utile\publicare_scripturi.ps1 # luna curenta, tot fluxul
|
||||
powershell -File COMUN\utile\publicare_scripturi.ps1 -Luna 2026-08 # alta luna
|
||||
powershell -File COMUN\utile\publicare_scripturi.ps1 -Fisier a.sql,b.sql # doar scripturile date
|
||||
```
|
||||
|
||||
Alte optiuni: `-DoarImport` (fara arhiva), `-DoarArhiva` (doar regenerare arhiva), `-Toate`
|
||||
(republica si scripturile identice), `-FaraVerificareZip`, `-Settings`, `-ZipPath`, `-DirScripturi`,
|
||||
`-Alias`, `-User`, `-Password`, `-SqlPlus`.
|
||||
|
||||
## Configurarea
|
||||
|
||||
Se citeste din `settings.ini`-ul lui `tasks.exe` (`D:\PROIECTE\fox\tasks\settings.ini`, schimbabil
|
||||
cu `-Settings`), aceleasi chei pe care le foloseste formularul; orice parametru dat explicit bate
|
||||
ini-ul.
|
||||
|
||||
| din ini | ce devine |
|
||||
|---|---|
|
||||
| `[connection] host_database` | nume de **DSN ODBC** — aliasul TNS e cheia `ServerName` a DSN-ului din registri (`CENTRAL` → `ROA_CENTRAL`) |
|
||||
| `[connection] username_database` / `password_database` | utilizatorul Oracle |
|
||||
| `[folder] script_folder` | directorul scripturilor, cu `\SCRIPTURI\` → `\SCRIPTURI_CLAR\` (+ `\<an>\<luna>\`) |
|
||||
| `[folder] roa_output` | + `_UPDATE\` = directorul arhivelor |
|
||||
| `[folder] sqlplus_exe` | clientul Oracle (si `TNS_ADMIN` = directorul lui) |
|
||||
| `[script]` | prefixele valide (`CO_`, `FF_`, `RF_`, `SYS_`, `JCS_`) — prefix necunoscut = avertisment |
|
||||
|
||||
`sqlplus_exe` arata spre `instantclient_19_18`; `instantclient_11_2_0_2` (valoarea de dinainte) are
|
||||
un `tnsnames.ora` vechi, cu `ROA_CENTRAL` pe `10.0.20.122` in loc de `.121`, deci conexiunea expira.
|
||||
`settings.ini` e local (ignorat de SVN).
|
||||
|
||||
## Cei doi pasi
|
||||
|
||||
**1. Import** — fiecare `.sql` intra ca un rand in `CONTAFIN_ORACLE.UPD_DATABASE` de pe `ROA_CENTRAL`,
|
||||
cu `SCRIPT_ORDER = 0` (randul contine scriptul intreg, nu instructiuni parsate), `SCRIPT_NAME` cu
|
||||
MAJUSCULE si `.SQL`, `SCRIPT_TYPE` = ce urmeaza dupa `NN_`, `SCRIPT_CONTENT` = fisierul in clar.
|
||||
`ID` vine din trigger, `DATAORA` din `SYSDATE` implicit, `SCRIPT_APPVER`/`SCRIPT_EXTRA_FILE` raman
|
||||
goale. Daca `SCRIPT_NAME` exista deja, se face **update pe acelasi `id`** — asa se republica un
|
||||
script corectat, pentru ca clientul face `MERGE ... on (a.id = b.id)`.
|
||||
|
||||
**2. Arhiva lunara** — in `Y:\ROAUPDATE\_UPDATE\` se scriu `database_YYYYMMDD_YYYYMMDD.zip` **si**
|
||||
`databasen_...zip` (identice azi: `database_` era varianta criptata cu `wrap.exe`, nu se mai
|
||||
foloseste). Fiecare contine XML-ul cu acelasi nume ca zip-ul (format `VFPData`/`crsxml`,
|
||||
Windows-1252, CRLF, tab-uri, `script_content` gol) plus cate un `<STEM_MAJUSCULE>.sql` per script.
|
||||
Indexii `roa_database.xml` / `roa_databasen.xml` listeaza arhivele existente si se schimba doar
|
||||
cand apare o luna noua.
|
||||
|
||||
Continutul din arhiva se citeste **inapoi din baza**, nu de pe disc — deci arhiva contine exact ce
|
||||
va primi clientul.
|
||||
|
||||
## Verificari facute automat
|
||||
|
||||
- fisier cu sfarsituri de linie LF: **refuzat** (parsarea pe client se face pe `CHR(13)+CHR(10)`);
|
||||
- dupa import, continutul e citit inapoi din CLOB si comparat octet cu octet cu fisierul; la
|
||||
diferenta se opreste inainte de arhiva;
|
||||
- scripturile deja publicate cu acelasi continut se sar (`-Toate` forteaza republicarea);
|
||||
- arhiva generata se citeste inapoi cu cititorul clientului (`pack_utils.decodebase64` +
|
||||
`zip_util_pkg.get_file`) si se compara lungime + MD5 per fisier — o arhiva facuta din PowerShell
|
||||
este citita corect de `zip_util_pkg`;
|
||||
- fisierele inlocuite din `_UPDATE` se copiaza intai in `_UPDATE\_backup\<data_ora>\`.
|
||||
|
||||
`Y:\ROAUPDATE\_UPDATE\` e **live**: clientii descarca de acolo imediat ce fisierul e pus.
|
||||
|
||||
## Ce face clientul
|
||||
|
||||
`PACK_UPDATE.UpdateScripts` (`COMUN\docs\PACK_UPDATE.pck`) descarca indexul, apoi arhivele care
|
||||
acopera perioada neaplicata, extrage XML-ul cu `zip_util_pkg.get_file`, face `MERGE` in
|
||||
`UPD_DATABASE` pe `id`, apoi pentru fiecare rand cu `script_extra_file` pune continutul fisierului
|
||||
in `script_content` — pentru `.sql` text clar, fara base64 (base64 e doar pentru instructiunile
|
||||
parsate, alta ramura). Actualizare blocata: `depanare-pack-update.md`.
|
||||
|
||||
## Detalii de implementare
|
||||
|
||||
Continutul circula **hexazecimal** in ambele sensuri (`utl_i18n.raw_to_char` / `string_to_raw` cu
|
||||
`WE8MSWIN1252`), pe bucati de 900 de octeti, in blocuri PL/SQL de cate 15 bucati. Motivul: baza e
|
||||
`AL32UTF8`, fisierele sunt CP1252, iar comanda trimisa lui `sqlplus` ramane ASCII pur — nu depinde
|
||||
de `NLS_LANG` si nu poate strica octetii >= 0x80. Consecinta utila: comparatia dintre fisier si
|
||||
CLOB e exacta, nu pe lungime.
|
||||
@@ -1,54 +1,134 @@
|
||||
# Reguli de lucru agent (comune proiectelor ROA VFP)
|
||||
|
||||
1. Modificari de cod: livreaza FISIER de diff `docs\diff_runda<N>_<subiect>.patch`
|
||||
(`git diff --no-index <baseline.bak> <editat>`), nu diff in terminal.
|
||||
Write-back in binar (txt2vcx) si commit DOAR dupa aprobarea patch-ului de catre utilizator.
|
||||
Patch-urile sunt intermediare de review: NU se comit NICIODATA in git (sunt in
|
||||
.gitignore ca `docs/diff_runda*.patch`); raman doar local, pe disc.
|
||||
Curatenie: dupa commit se sterg patch-urile de review si backup-urile de lucru
|
||||
(`*.pre_runda*.bak`).
|
||||
2. Comentarii in cod: istoricul modificarilor sta DOAR in ANTETUL fisierului, niciodata inline.
|
||||
Se aplica la fel in `.prg` si in package-urile/procedurile PL/SQL Oracle.
|
||||
In corpul codului sunt permise numai comentarii FUNCTIONALE (ce face codul si de ce, acolo
|
||||
unde nu se vede din cod) - niciodata "am adaugat / am modificat / am sters", data sau autor.
|
||||
In ANTET se tine o singura intrare CUMULATIVA per functionalitate, scurta si compacta, in stilul
|
||||
existent (`*!* DD.MM.YYYY` / `*!* autor` / `*!* ce face, 1-2 fraze`): la revenirea pe aceeasi
|
||||
lucrare se rescrie intrarea, nu se adauga alta. Autorul e persoana care semneaza livrarea
|
||||
(ex. `marius.mutu`) - niciodata "claude" sau alt nume de agent.
|
||||
Se descrie doar comportamentul final, fara referinte la revizii, runde, patch-uri sau la
|
||||
corectii facute pe parcurs. La rezolvari de erori NU se adauga comentarii deloc.
|
||||
Explicatiile merg in docs/ sau in mesajul de commit, nu in cod.
|
||||
Changelog (`changelog_<aplicatie>.txt`): text minimal, pe limba utilizatorului, nu tehnic,
|
||||
o fraza scurta per intrare. Cat timp lucrarea nu a ajuns la utilizatori (fara deploy),
|
||||
erorile introduse si corectate in interiorul ei NU se pomenesc - intrarea descrie
|
||||
functionalitatea asa cum ajunge la utilizator, `:nou:`/`:modificare:`; `:eroare:` ramane
|
||||
doar pentru erori care au fost in productie.
|
||||
3. Modificari minime: doar ce s-a cerut; fara refactorizari sau curatenie din oficiu.
|
||||
4. Testare headless (fara IDE): `vfp9.exe -A -T "<script.prg>" <param>` din PowerShell.
|
||||
Mediu, sabloane, capcane si metoda de depanare: `depanare_testare_vfp.md`.
|
||||
5. Editare .vcx/.scx pe text (cache, cp1252 byte-safe, fidelity-check): `flux-editare-vfp-text.md`.
|
||||
Cautare in binare: `cautare_vcx_vct.md`.
|
||||
Versiunile `.??2` sunt instantanee si pot fi mai vechi decat binarul - verifica mtime-ul
|
||||
inainte de a trage concluzii din ele; continutul real al proiectului se citeste din `.PJX`.
|
||||
6. Misiuni lungi (teste, investigatii, sarcini inlantuite): NU un singur subagent cu context
|
||||
acumulat — orchestrator + subagenti proaspeti per sarcina (max ~200-250k tokens/subagent),
|
||||
handoff compact pe disc: `orchestrare-subagenti.md`.
|
||||
7. Conventii obligatorii, de citit cand atingi zona respectiva:
|
||||
- editezi orice fisier cu octeti cp1252 - `.vc2`/`.sc2`, dar si `.prg` (ex. `programe\ocautare.prg`,
|
||||
unde `s`-urile cu virgula din `masina`/`si contul`/`transa` sunt octetul `0xBA`) ->
|
||||
`conventie_encoding_cp1252.md`. Orice write cu un tool care nu scrie cp1252 nativ (Edit/Write)
|
||||
corupe caracterele >= 0x80 din TOT fisierul (`0xBA` -> `EF BF BD`), chiar daca schimbi o singura
|
||||
linie, si o face din nou la FIECARE scriere. Deci: editezi tot ce ai de editat, si abia DUPA ultima
|
||||
scriere verifici byte-level si repari o singura data; daca mai editezi dupa reparare, se strica iar.
|
||||
Verificare: `perl -ne 'print "$.\n" if /[\x80-\xFF]/' <fisier>`; reparare (aici pentru `0xBA`):
|
||||
`perl -e 'binmode(STDIN);binmode(STDOUT);local $/;$_=<STDIN>;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp`.
|
||||
ATENTIE: `EF BF BD` nu spune ce caracter s-a pierdut - toate diacriticele devin la fel. Ia octetul
|
||||
corect per pozitie din `svn cat <fisier>` (SVN are versiunea necorupta) si abia apoi inlocuieste;
|
||||
o inlocuire oarba cu `0xBA` strica `a`/`t` cu caciula (`0xE3`, `0xFE`) din alte fisiere;
|
||||
- adaugi/rearanjezi controale pe formulare sau coloane in grid -> `conventie_ux_formulare.md`;
|
||||
- scrii cod cu `GO` pe un `Recno()` capturat sau primit ca parametru -> `conventie_go_recno.md`;
|
||||
- `ALTER TABLE` pe cursorul intors de `goExecutor.oExecute()` -> `conventie_goexecutor_alter_table.md`;
|
||||
- testare UI / prin MCP -> `testare-ui-vfp.md`, `testare-vfp-mcp.md`;
|
||||
- export date din Oracle -> `oracle_export.md`;
|
||||
- modifici schema Oracle (tabele/view-uri/pachete) -> `scripturi-migrare-db.md`
|
||||
(unde stau scripturile de migrare si modelele pentru scripturi noi).
|
||||
# Reguli de lucru agent (comune proiectelor ROA VFP)
|
||||
|
||||
1. Modificari de cod: diff ca FISIER `docs\diff_runda<N>_<subiect>.patch`
|
||||
(`git diff --no-index <baseline.bak> <editat>`), nu in terminal. **COMMIT-ul** e singurul pas
|
||||
care asteapta aprobarea patch-ului. Write-back-ul in binar (txt2vcx) si testele se fac IMEDIAT
|
||||
dupa editarea `.vc2`/`.sc2`, fara sa astepti raspunsul — inclusiv pe `COMUN` — ca sa ajungi la
|
||||
review cu rezultatele testelor, nu cu o propunere netestata; daca nu merge, revii cu
|
||||
`git checkout` pe binare (`.vcx`+`.vct`) sau cu write-back din `*.pre_runda*.bak`.
|
||||
Patch-urile (in .gitignore, `docs/diff_runda*.patch`) nu se comit niciodata, raman local.
|
||||
Curatenia de dinainte de commit NU se face pe cap de agent, ci cu
|
||||
`powershell -File COMUN\utile\curatenie.ps1` (`-DryRun` listeaza fara sa stearga): patch-uri,
|
||||
handoff-uri/planuri de runda, `*.pre_runda*.bak`, `.bak`-urile din cache-ul text si artefactele
|
||||
de test (`screenshots*`, `uisync*`, `.fxp`, `.err`, loguri). Sterge doar fisiere neurmarite de
|
||||
git — cele tracked sunt sarite.
|
||||
2. Comentarii in cod SI in scripturile de migrare `.sql`: minime, strict functionale, descriu
|
||||
comportamentul CURENT (ca si cum ar fi scris asa de la inceput). **Doar daca e cazul** — un
|
||||
comentariu se scrie acolo unde explica o **ramura** sau un **filtru** care nu se citeste singur,
|
||||
ca sa se inteleaga codul; unde codul e limpede, nu se comenteaza. O linie de regula, 2-3 doar
|
||||
pentru metode cu contract nebanal (parametri, cursor asteptat/lasat deschis, pozitionare la
|
||||
iesire), 4-5 in antetul unui script de migrare (ce e obiectul si ce contract are). Istoricul
|
||||
modificarilor sta DOAR in ANTETUL fisierului (niciodata inline) — la fel in `.prg`, in `.sql`
|
||||
si in PL/SQL Oracle.
|
||||
INTERZIS in comentariu: nume de agent ("claude"), referinte la planuri, stories, propuneri,
|
||||
decizii, etape sau erori (`docs/plan_*.md`, `docs/propuneri_*.md`, "#6", "S4", "M2", "T3",
|
||||
"dec.6", "runda27", "E7", "D-H2"), trimiteri la rapoartele din `docs/` ("vezi raportul,
|
||||
sectiunea ..."), justificarea alegerii facute (de ce numele acesta, de ce s-a respins varianta
|
||||
cealalta), istoricul modificarii ("inlocuieste...", "nu mai depinde de...", "mutat din..."),
|
||||
date si autori pe cod nou.
|
||||
Comentarii vechi in stil jurnal nu se rescriu din oficiu — doar cand blocul e oricum atins
|
||||
sau la cerere explicita.
|
||||
Antet: o singura intrare CUMULATIVA per functionalitate (`*!* DD.MM.YYYY` / `*!* autor` /
|
||||
`*!* ce face, 1-2 fraze`) — la revenire se rescrie intrarea, nu se adauga alta; autorul e cine
|
||||
semneaza livrarea (ex. `marius.mutu`), niciodata agent. Doar comportamentul final — fara
|
||||
revizii/runde/patch-uri/corectii. La rezolvari de erori: fara comentarii.
|
||||
Explicatiile merg in docs/ sau in mesajul de commit, nu in cod.
|
||||
Changelog (`changelog_<aplicatie>.txt`): strictul necesar, pe limba utilizatorului, non-tehnic
|
||||
— 1-3 fraze/intrare, fara detalii de implementare, fara enumerarea locurilor atinse. Cat timp
|
||||
lucrarea n-a ajuns la utilizatori, erorile introduse si corectate in interior NU se mentioneaza
|
||||
— intrarea descrie functionalitatea finala, `:nou:`/`:modificare:`; `:eroare:` doar pentru erori
|
||||
care au fost in productie.
|
||||
3. Modificari minime si SCOPED: doar ce s-a cerut, doar pe cazul cu problema, fara refactorizari
|
||||
din oficiu. Cauta intai ce exista (`inventar-comun.md`) si refoloseste; daca lipseste ceva,
|
||||
propune COMPLETAREA unei functii/tabele/view comune, nu o varianta paralela. 80/20: solutia cea
|
||||
mai simpla care rezolva cazul real. Completeaza `inventar-comun.md` la orice descoperire/creare
|
||||
de element comun nedocumentat.
|
||||
**Cod nou: clase in `.prg`, nu metode in `.vcx`/`.scx`.** Logica se incapsuleaza intr-o clasa
|
||||
(`Define Class ... As Custom`) dintr-un `.prg`; formularul sau clasa vizuala doar instantiaza
|
||||
obiectul (`Createobject`) si il apeleaza, metoda din binar ramanand un apel de o linie. Sablon:
|
||||
`COMUN\programe\anaf_efactura.prg` (`AnafeFacturaServer`, `ANAFeFactura`), apelat din
|
||||
`clase\anaf_efactura.vcx`. Motivul e de intretinere: un `.prg` se editeaza direct si diff-ul lui
|
||||
se citeste in git, pe cand codul pus ca metoda in binar trece prin FoxBin2Prg si write-back si
|
||||
se urmareste greu.
|
||||
4. Testare headless (fara IDE): `vfp9.exe -A -T "<script.prg>" <param>` din PowerShell.
|
||||
Mediu, sabloane, capcane, depanare: `depanare_testare_vfp.md`.
|
||||
5. Editare .vcx/.scx pe text (cache, cp1250 byte-safe, fidelity-check): `flux-editare-vfp-text.md`.
|
||||
Cautare in binare: `cautare_vcx_vct.md`. Versiunile `.??2` sunt instantanee, pot fi mai vechi
|
||||
decat binarul — verifica mtime inainte de concluzii; continutul real e in `.PJX`.
|
||||
6. Delegare: implementarile, testele, verificarile si cercetarile se dau unor subagenti Sonnet in
|
||||
background (lane-uri paralele); sesiunea principala doar orchestreaza si verifica, ca sa nu i
|
||||
se umple contextul. Misiuni lungi: subagenti proaspeti per sarcina (max ~200-250k
|
||||
tokens/subagent), nu unul singur cu context acumulat; handoff compact pe disc:
|
||||
`orchestrare-subagenti.md`.
|
||||
**Verificarea a ce se intoarce** — pentru executie delegarea merge, pentru concluzii nu:
|
||||
- **citeste contractul functiei apelate, nu-l presupune.** Un raport care descrie corect
|
||||
structura codului poate gresi sensul: ex. `goExecutor.oExecute` intoarce succes/insucces
|
||||
(`CT_SUCCES`/`CT_INSUCCES`), NU numarul de randuri — o garda `If lnSucces > 0` citita ca
|
||||
"are randuri" a produs un bug inexistent, raportat ca blocant. Deschide functia.
|
||||
- **fix ingust, nu supra-constructie.** Cand premisa se corecteaza, corectia se restrange:
|
||||
mecanismele noi introduse "ca sa fie sigur" diverg de la codul-sablon si blocheaza
|
||||
refolosirea lui in alta parte.
|
||||
- **"zero cazuri in date" nu dovedeste nimic** pe scheme cu date de test; raspunsul vine din
|
||||
cod. Si invers: o potrivire de cifre pe 1-2 documente nu e o regula.
|
||||
- **cere raportul sa separe "testat" de "analizat static"**, si ce n-a putut fi acoperit. Un
|
||||
agent care nu e intrebat explicit va prezenta amandoua la fel.
|
||||
- **spune-i ca poate infirma briefingul.** Altfel implementeaza corectia ceruta chiar cand a
|
||||
descoperit ca nu e nevoie de ea.
|
||||
7. Conventii obligatorii, de citit cand atingi zona respectiva:
|
||||
- editezi fisiere `.vc2`/`.sc2`, dar si `.prg` (ex. `programe\ocautare.prg`, unde `s`-urile cu
|
||||
virgula din `masina`/`si contul`/`transa` sunt octetul `0xBA`) -> `conventie_encoding_cp1252.md`.
|
||||
Antetul FoxBin2Prg declara `CPID="1252"`, dar octetii diacriticelor sunt de fapt **cp1250**
|
||||
(`0xE3`=a cu caciula, `0xFE`=t cu virgula, `0xAA`=S majuscul cu virgula, `0xBA`=s minuscul cu
|
||||
virgula) - nu trata eticheta din antet ca adevarul despre encoding. Orice write cu un tool ce
|
||||
nu pastreaza octetii nativ (Edit/Write) corupe caracterele >= 0x80 din TOT fisierul (`0xBA` ->
|
||||
`EF BF BD`), chiar la o singura linie schimbata, si o repeta la FIECARE scriere - **nu
|
||||
re-encoda niciodata fisierul: lucreaza pe octeti (`byte[]`) sau scrie strict ASCII in
|
||||
continutul nou**; editeaza tot ce ai de editat, verifica byte-level si repara o singura data
|
||||
DUPA ultima scriere.
|
||||
Cens obligatoriu **inainte SI dupa** fiecare editare, care trebuie sa ramana identic:
|
||||
`od -An -tx1 <fisier> | tr ' ' '\n' | grep -v '^$' | awk '$1>"7f"' | sort | uniq -c`. Atentie
|
||||
la sens: la stricare censul **CRESTE**, nu scade - un octet cp1250 devine 3 octeti `EF BF BD`
|
||||
(U+FFFD) la o re-encodare UTF-8 gresita; cauta explicit secventa `EF BF BD`, nu doar tiparul
|
||||
generic de mojibake `C3`/`C4`/`C5`/`C8` + octet de continuare (acela da fals-pozitiv pe text
|
||||
UTF-8 legitim sau pe comentarii intr-o alta limba, deja intalnite in cod). Verificare veche
|
||||
(orice octet >=0x80, utila cand cauti pozitia exacta): `perl -ne 'print "$.\n" if
|
||||
/[\x80-\xFF]/' <fisier>`; reparare (pt. `0xBA`): `perl -e
|
||||
'binmode(STDIN);binmode(STDOUT);local $/;$_=<STDIN>;s/\xEF\xBF\xBD/\xBA/g;print' < f > f.tmp`.
|
||||
`EF BF BD` nu spune ce caracter s-a pierdut - toate diacriticele devin la fel; ia octetul corect
|
||||
per pozitie din `svn cat <fisier>` (necorupt) sau din git history (`git cat-file blob
|
||||
<commit>:<cale>`, **din Bash, niciodata cu `>` din PowerShell 5.1** - adauga BOM si
|
||||
re-encodeaza) inainte sa inlocuiesti - o inlocuire oarba cu `0xBA` strica `a`/`t` cu caciula
|
||||
(`0xE3`, `0xFE`) din alte fisiere;
|
||||
- adaugi/rearanjezi controale pe formulare sau coloane in grid -> `conventie_ux_formulare.md`;
|
||||
- grid needitabil pe formular cu 2+ grid-uri -> `capcana_grid_controlsource.md`;
|
||||
- adaugi o coloana intr-un grid deja livrat (ordinea din clasa e neutralizata de
|
||||
preferintele salvate per utilizator) -> `capcana_grid_preferinte_utilizator.md`;
|
||||
- `GO` pe un `Recno()` capturat/primit ca parametru -> `conventie_go_recno.md`;
|
||||
- `ALTER TABLE` pe cursorul intors de `goExecutor.oExecute()` -> `conventie_goexecutor_alter_table.md`;
|
||||
- testare UI / prin MCP -> `testare-ui-vfp.md`, `testare-vfp-mcp.md`;
|
||||
- garzi pe valori NULL din Oracle -> `conventie_null_vfp.md`;
|
||||
- export date din Oracle -> `oracle_export.md`;
|
||||
- actualizarea ROA nu se finalizeaza (job update, PACK_UPDATE) -> `depanare-pack-update.md`;
|
||||
- modifici schema Oracle (tabele/view-uri/pachete) -> `scripturi-migrare-db.md`.
|
||||
8. Eroare raportata de utilizator: nu analiza statica indelungata — scrie intai un test care o
|
||||
reproduce pe fluxul real; el da cauza si confirma remedierea. Analiza statica doar cat sa stii
|
||||
ce sa pui in test.
|
||||
9. Context sesiune principala: la peste **250k** salveaza contextul intr-un handoff pe disc, il
|
||||
predai unei sesiuni noi si te opresti. Limita maxima absoluta: **275k**. Nu estima - masoara:
|
||||
hook-ul din `monitorizare-context.md` anunta pragul la fiecare mesaj.
|
||||
10. Fisier de progres MASTER per proiect (`docs\progres.md`): la zi pe tot parcursul, nu doar la
|
||||
predare — stare curenta, facut/testat, ipoteze excluse (cu dovada), ce urmeaza, fisiere atinse,
|
||||
comenzi de rulat. O sesiune noua porneste de acolo, fara sa reia investigatia. E ajutor de
|
||||
predare, nu documentatie: dupa commit, cu toate sarcinile terminate, se sterge.
|
||||
11. La final de lucrare/cercetare: **propune** actualizarea documentatiei — `COMUN\docs\` daca e
|
||||
comun tuturor aplicatiilor, `docs\` al proiectului daca e specific (plus `inventar-comun.md`,
|
||||
regula 3). Doar relevant si reutilizabil (80/20): flux ascuns, capcana, procedura/tabela cheie
|
||||
— nu tot ce ai atins, nu verbose. Cateva randuri; propui, nu scrii din oficiu.
|
||||
O notita = regula + strictul de context ca sa fie aplicabila: fara cazul particular in care ai
|
||||
gasit-o, fara simptomele lantului de erori, fara ce se deduce din cod (cititorul stie deja).
|
||||
12. Revizuire periodica a documentatiei (`COMUN\docs\`, `docs\` al proiectului, inclusiv acest
|
||||
fisier): compacteaza pastrand semantica — taie ce se deduce din cod, exemplele repetate,
|
||||
istoricul, tot ce nu mai schimba o decizie. Scopul: docs + reguli sa ocupe cat mai putin context
|
||||
la incarcare. Propui rezultatul, nu rescrii din oficiu; nu pierzi nicio regula/capcana, doar
|
||||
cuvintele in plus. Fisierele de reguli/conventii se completeaza doar cu ce e super-util,
|
||||
simplu si concis. Cadenta o da hook-ul din `monitorizare-context.md` (marker la 30 de zile).
|
||||
|
||||
@@ -1,18 +1,139 @@
|
||||
# Scripturi migrare baza de date Oracle
|
||||
|
||||
Scripturile de migrare a schemei (si modelele pentru scripturi noi) sunt in
|
||||
`DATABASE\SCRIPTURI_CLAR` de sub radacina suitei ROA (folderul parinte al aplicatiei,
|
||||
`gcDirMare`/`dirgen` — ex. `D:\ROA\DATABASE\SCRIPTURI_CLAR`).
|
||||
Sursa SVN: `http://svnroa:3001/svn/ROA/DATABASE/Branches/RB-1.00`.
|
||||
Pentru un script nou, urmeaza formatul/conventiile celor recente de acolo.
|
||||
`DATABASE\SCRIPTURI_CLAR` de sub radacina suitei ROA (`gcDirMare`/`dirgen` — ex.
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR`). Sursa SVN: `http://svnroa:3001/svn/ROA/DATABASE/Branches/RB-1.00`.
|
||||
Pentru un script nou, urmeaza formatul/conventiile celor recente de acolo. Publicarea catre clienti
|
||||
(import in `UPD_DATABASE` + arhiva lunara): `publicare-scripturi-db.md`.
|
||||
|
||||
Reguli confirmate de Marius (24.07.2026):
|
||||
|
||||
- **Line-endings CRLF obligatoriu** in scripturile `.sql` — tool-urile agentului scriu
|
||||
implicit LF; dupa orice scriere, verifica si converteste byte-safe LF -> CRLF (fara
|
||||
decodare/reincodare). Parsarea pe fluxul ROA (ex. `ALINES` pe `CHR(13)+CHR(10)`)
|
||||
esueaza silentios pe LF: tot fisierul devine un singur rand.
|
||||
- `versiune_db.txt` (marker-ul `YYYY_MM_DD_NN` din radacina aplicatiei) se scrie fara
|
||||
newline la final (conventia existenta).
|
||||
- Aplicarea prin ODBC/`goExecutor`: sintaxa SQL*Plus `exec pachet.procedura(...)` nu
|
||||
functioneaza — foloseste `begin pachet.procedura(...); end;`.
|
||||
- **Line-endings CRLF obligatoriu** in scripturile `.sql` — tool-urile agentului scriu implicit
|
||||
LF; dupa orice scriere, verifica si converteste byte-safe LF -> CRLF (fara decodare/reincodare).
|
||||
Parsarea pe fluxul ROA (ex. `ALINES` pe `CHR(13)+CHR(10)`) esueaza silentios pe LF: tot fisierul
|
||||
devine un singur rand.
|
||||
- `versiune_db.txt` (marker-ul `YYYY_MM_DD_NN` din radacina aplicatiei) se scrie fara newline la
|
||||
final (conventia existenta).
|
||||
- Aplicarea prin ODBC/`goExecutor`: sintaxa SQL*Plus `exec pachet.procedura(...)` nu functioneaza
|
||||
— foloseste `begin pachet.procedura(...); end;`.
|
||||
- **Niciun `;` la capat de linie intr-un comentariu `--` din interiorul unei instructiuni.** SQL*Plus
|
||||
termina instructiunea acolo, chiar daca `;`-ul e in comentariu: restul `CREATE VIEW`-ului ajunge sa
|
||||
fie interpretat linie cu linie ca si comenzi, cu zeci de `SP2-0734` si un `ORA-00936` derutant care
|
||||
arata spre comentariu. Pus la sfarsit de fraza, `.` in loc de `;`. Comentariile de **dinaintea**
|
||||
instructiunii nu sunt afectate.
|
||||
- **Fiecare script se incheie cu `exec pack_migrare.UpdateVersiune('<nume_script>');` urmat de
|
||||
`commit;`.** Numele se da **fara extensia `.sql`** — o adauga `UpdateVersiune`; trecuta si in
|
||||
argument, ajunge in `VERSIUNE` ca `..._.sql.sql` si scriptul apare ca neaplicat la comparatia de
|
||||
mai jos. Toate scriptele din `SCRIPTURI_CLAR` o omit, iar in `VERSIUNE` nu exista niciun rand cu
|
||||
dubla extensie.
|
||||
DDL-ul comite implicit, dar `UpdateVersiune` e DML: fara `commit` explicit, un script
|
||||
se poate aplica fara ca versiunea sa se inregistreze, iar `VERSIUNE` ajunge sa minta despre ce s-a
|
||||
aplicat.
|
||||
- **Rularea manuala se face conectat pe schema tinta** (`CONTAFIN_ORACLE` pentru `co_`, schema firmei
|
||||
pentru `ff_`), niciodata cu un user de lucru. DDL-ul neprefixat (`create or replace package ...`)
|
||||
merge pe schema conexiunii: pe alt user iese `PLS-00304` si ramane un obiect orfan, iar pachetul
|
||||
tinta ramane neschimbat. In acelasi script, DML-ul pe tabele cu sinonim public nimereste tabela
|
||||
reala si pare ca totul a mers — verifica intotdeauna iesirea sqlplus si `all_objects`.
|
||||
`PACK_UPDATE` face `CONNECT <schema>/<parola>@ROA` real per schema (`UpdateSchemaSQLPLUS`, parola
|
||||
din `SERVER_INFO`), deci scriptul neprefixat e corect pentru livrare.
|
||||
|
||||
## Sursa de referinta pentru DDL: MARIUSM_AUTO, nu productia
|
||||
|
||||
Regula lui Marius (06.08.2026): **orice modificare de tabela, view, procedura, functie sau pachet se
|
||||
scrie plecand de la sursa din schema de dezvoltare `MARIUSM_AUTO` (`ROA_CENTRAL`), niciodata de la
|
||||
sursa citita dintr-o schema de client** (`VENDING`, `ACN`, ...). Schemele de client raman in urma:
|
||||
pot avea scripturi neaplicate sau variante livrate separat (ex. pachetele `_10G_ROMCONSTRUCT`), iar o
|
||||
modificare scrisa peste o sursa veche sterge corectii deja livrate.
|
||||
|
||||
Schemele de client raman utile doar pentru **masuratori pe date reale**, in citire.
|
||||
|
||||
### Verifica intai ca MARIUSM_AUTO e la zi
|
||||
|
||||
"Ultima versiune din dev" e ultima versiune doar daca toate scripturile din `SCRIPTURI_CLAR` chiar au
|
||||
fost aplicate acolo. `pack_migrare.UpdateVersiune` inregistreaza fiecare script aplicat in tabela
|
||||
`VERSIUNE` (`script_final` = numele fisierului, cu tot cu `.sql`), deci diferenta se vede direct:
|
||||
|
||||
```sql
|
||||
select script_final, data_final from versiune order by data_script desc, seq_script desc;
|
||||
```
|
||||
|
||||
```powershell
|
||||
Get-ChildItem D:\ROA\DATABASE\SCRIPTURI_CLAR -Recurse -Filter *.sql |
|
||||
Select-Object -ExpandProperty Name | Sort-Object
|
||||
```
|
||||
|
||||
Daca lipsesc scripturi din `VERSIUNE`, **nu porni modificarea** pe sursa de acolo — semnaleaza-i lui
|
||||
Marius ce nu e aplicat. Exportul sursei de referinta: `oracle_export.md`.
|
||||
|
||||
## Continutul unui script
|
||||
|
||||
- **Minimul necesar si intotdeauna SCOPED**: `update`/`insert` doar pe randurile cazului tratat
|
||||
(setul, codul, firma anume), niciodata pe toate randurile care "seamana" cu el.
|
||||
- **Fara `select` de raportare in script** — nu-l citeste nimeni la aplicare si poate da eroare.
|
||||
Verificarile se fac inainte, separat, pe schema de lucru.
|
||||
- **Idempotent**: rulat de doua ori nu mai schimba nimic (`merge`, `where <coloana> is null`).
|
||||
- **Un pachet sta singur in scriptul lui**, fara alt DDL sau DML alaturi: modificarile de tabele si
|
||||
curateniile de date merg in scripturi separate, cu numar propriu.
|
||||
- **Comentarii strict necesare**, ca in cod: antet de 4-5 randuri (data + autor, ce e obiectul, ce
|
||||
contract are), fara referinte la planuri, stories, propuneri, decizii sau erori, fara trimiteri la
|
||||
rapoartele din `docs/`, fara justificarea alegerilor si fara istoricul modificarii. Regula completa
|
||||
si lista de interdictii: `reguli_lucru.md`, punctul 2.
|
||||
|
||||
## Compatibilitate cu serverele clientilor
|
||||
|
||||
Serverul de dezvoltare e mai nou decat serverele clientilor, deci un script care trece local poate
|
||||
pica la client si opri actualizarea.
|
||||
|
||||
Parcul de servere (03.08.2026): **un client pe Oracle 10.2** (ROMCONSTRUCT), cativa pe **XE 11 si
|
||||
11g** standard, restul pe **XE 18/19/21 si 18/21**.
|
||||
|
||||
**Regula: orice script care ajunge in comune se scrie la nivelul Oracle 10.2 si trebuie sa ruleze pe
|
||||
10.2 si pe 11.x.** Numitorul comun e 10.2 — nu se folosesc facilitati 11g si cu atat mai putin 12c+,
|
||||
oricat de comod ar fi pe dev. Proba inainte de publicare se face pe serverul cel mai vechi
|
||||
(ROMCONSTRUCT), nu pe dev.
|
||||
|
||||
Constructii care merg pe dev si pica mai jos:
|
||||
|
||||
| Constructie | Disponibila de la | Ce iese sub ea |
|
||||
|---|---|---|
|
||||
| identificator peste 30 de caractere (tabela, index, constrangere, coloana) | 12.2 | `ORA-00972` |
|
||||
| `REGEXP_COUNT` | 11.1 | `ORA-00904` in SQL / `PLS-00201` in PL/SQL |
|
||||
| `CONTINUE` (instructiune PL/SQL) | 11.1 | `PLS-00201: identificatorul 'CONTINUE' trebuie declarat` |
|
||||
| `LISTAGG` | 11.2 | `ORA-00904` |
|
||||
| `PIVOT` / `UNPIVOT` | 11.1 | eroare de sintaxa |
|
||||
| trigger compus (`COMPOUND TRIGGER`) | 11.1 | eroare de compilare |
|
||||
| `secventa.NEXTVAL` direct intr-o atribuire PL/SQL | 11.1 | `PLS-00357` (pe 10g: `select ... into` din `dual`) |
|
||||
| `FETCH FIRST n ROWS`, `CROSS APPLY`, `LATERAL` | 12.1 | eroare de sintaxa (pe 10g/11g: `rownum`) |
|
||||
| `IDENTITY`, `DEFAULT ON NULL`, coloane invizibile | 12.1 | eroare de sintaxa |
|
||||
| `VALIDATE_CONVERSION`, `CAST ... DEFAULT ON CONVERSION ERROR` | 12.2 | `ORA-00904` |
|
||||
| `FORALL` cu campuri de record din colectie (`S(i).camp`) | 11.1 | `PLS-00436` / `PLS-00382` |
|
||||
|
||||
Editiile **XE** adauga limite proprii, independent de sintaxa: XE 11.2 nu are partitionare, executie
|
||||
paralela si nici masina virtuala Java in baza; XE 18/19/21 au setul de facilitati al editiei mari,
|
||||
dar plafonate pe resurse (12 GB de date, 2 GB RAM, 2 fire de executie). Deci nimic care sa depinda de
|
||||
partitionare sau de Java in baza, si nicio operatie care sa presupuna spatiu/memorie de server mare.
|
||||
|
||||
Plus, independent de versiune: **un obiect nu se poate referi la ceva creat de un script ulterior.**
|
||||
Pe dev obiectul exista deja, deci pachetul compileaza; la client scriptele se aplica in ordine si
|
||||
iese `ORA-00942` / corp invalid. Cand un script creeaza o tabela si altul un pachet care o foloseste,
|
||||
tabela trebuie sa fie prima in ordinea `YYYY_MM_DD_NN`.
|
||||
|
||||
Un pachet care nu are echivalent 10g se livreaza ca varianta separata pentru serverul acela
|
||||
(ex. `ff_..._PACK_CONTAFIN_10G_ROMCONSTRUCT.pck`). La aplicarea manuala a unei astfel de variante se
|
||||
compileaza **doar PACKAGE BODY-ul**: recrearea specificatiei invalideaza dependentele si da
|
||||
`ORA-04068` utilizatorilor conectati. Inainte, verifica ca specificatia din fisier e identica cu cea
|
||||
de pe server.
|
||||
|
||||
Verificarea erorii se face in `C:\DMPDIR\script_master.log` de pe serverul clientului
|
||||
(`depanare-pack-update.md`) — nu apare in `UPD_LOG`.
|
||||
|
||||
## Numerotare si versiune_db.txt
|
||||
|
||||
Numele scriptului: `<prefix>_YYYY_MM_DD_NN_<subiect>.sql`. Prefixe in uz: `ff` (schema fiecarei
|
||||
firme), `co` (`CONTAFIN_ORACLE`), `sys`, `ris`, `rf`.
|
||||
|
||||
- **`NN` e o secventa unica pe zi, comuna tuturor prefixelor** — un numar consumat de un `co_`
|
||||
nu se reia intr-un `ff_` din aceeasi zi si invers.
|
||||
- In `versiune_db.txt` (radacina aplicatiei) se trece **doar versiunea ultimului script `ff_`**:
|
||||
programele se conecteaza pe schema firmei, nu pe `CONTAFIN_ORACLE`, deci markerul urmareste
|
||||
numai migrarile aplicate acolo.
|
||||
|
||||
34
docs/scripturi-uzuale.md
Normal file
34
docs/scripturi-uzuale.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Scripturi uzuale (sarcini repetitive)
|
||||
|
||||
**Regula: o sarcina care se repeta se pune intr-un script si de atunci se apeleaza scriptul.**
|
||||
Nu reface lantul de pasi din memorie la fiecare sesiune si nu da unui subagent aceleasi instructiuni
|
||||
a doua oara — daca a doua oara e nevoie de acelasi lucru, scrie scriptul.
|
||||
|
||||
| Cand | Ce rulezi | Ce face |
|
||||
|---|---|---|
|
||||
| inceput de sesiune, si dupa orice `svn update` | `roa_sync.bat` din radacina proiectului (→ `COMUN\scripts\roa_sync.ps1`) | `svn update` → `git_sync` (texte `.??2`) → commit `sync SVN r<rev>` → reconciliere cu `origin` (ff/rebase) → push conditionat → inchide branch-urile `claude/*` terminate |
|
||||
| inainte de un commit | `COMUN\utile\curatenie.ps1` (`-DryRun` doar listeaza) | sterge artefactele de lucru netrackuite: patch-uri de review, `handoff*`/`runda*`/`propuneri_*`, backup-uri `*.pre_runda*.bak`, artefacte de test |
|
||||
| la "commit / push" | `COMUN\utile\livrare.ps1 -Mesaj "..." [-Comun]` | `git_sync` → `curatenie` → verificari de livrare → status/diff pe ambele repo-uri → commit + push. `COMUN` doar cu `-Comun`; `push --force` nu exista |
|
||||
| editare `.vcx`/`.scx` | `D:\ROA\UTIL\foxbin2prg\` : `git_sync.ps1`, `vfp_symbols.ps1`, `txt2vcx.ps1` | reimprospatare text in-arbore, index de simboluri, write-back cu fidelity-check |
|
||||
| actualizare de baza de date blocata | `COMUN\utile\diag_actualizare.ps1 -Alias <TNS>` | `UPD_ISTORIC` → `UPD_LOG` → `script_master.log` → versiuni per schema → job → tablespace → verdict. Vezi `depanare-pack-update.md` |
|
||||
| spatiu plin la un client | `COMUN\utile\diag_spatiu.ps1 -Alias <TNS> [-Disc] [-SysPassword]` | tablespace, audit, ADR, FRA, disc server, top segmente. Vezi `depanare-spatiu-oracle.md` |
|
||||
| publicare scripturi de baza de date | `COMUN\utile\publicare_scripturi.ps1 [-Luna YYYY-MM] [-Fisier ...] [-DryRun]` | import in `UPD_DATABASE` → arhiva lunara `database[n]_*.zip` + indexi in `_UPDATE`, cu verificare octet cu octet. Vezi `publicare-scripturi-db.md` |
|
||||
| teste UI VFP | harness din `COMUN\utile\Teste` | vezi `testare-ui-vfp.md` |
|
||||
| citirea emailurilor de pe conturile romfast | `COMUN\utile\citeste_email.ps1 [-Cauta ...] [-Nr <linie>]` | listeaza/extrage mesaje din mbox-urile Thunderbird Portable (conectorul Gmail nu vede conturile romfast). Vezi `email-thunderbird.md` |
|
||||
|
||||
Documentatia **nu** se genereaza automat si nu exista niciun hook care s-o scrie — `livrare.ps1`
|
||||
doar semnaleaza ce lipseste (changelog neatins, binar VFP fara textul lui sincronizat).
|
||||
|
||||
Candidati inca nescrisi: un helper pentru rulat SQL prin `sqlplus` (fisier ASCII + `@fisier.sql`,
|
||||
refacut manual la fiecare interogare) si un wrapper care ruleaza `diag_spatiu.ps1` peste toti
|
||||
clientii, cu un rezumat pe un rand per server.
|
||||
|
||||
Fluxul SVN ↔ git din spatele lui `roa_sync`: `fluxul_svn_git.md`.
|
||||
|
||||
**Mesaje de commit din PowerShell catre `git`/`svn` (exe native): niciodata `-m $mesaj`.**
|
||||
PowerShell nu escapeaza ghilimele/backtick/`$` cand paseaza argumente catre un exe nativ - un
|
||||
mesaj cu `"..."` sparge comanda. Solutie: scrie mesajul intr-un fisier temporar si foloseste
|
||||
`git commit -F <fisier>` / `svn commit -F <fisier>`, cu textul **UTF-8 fara BOM**
|
||||
(`[IO.File]::WriteAllText($cale, $mesaj, (New-Object Text.UTF8Encoding $false))` - `Out-File
|
||||
-Encoding utf8` in PS 5.1 scrie BOM, care ajunge ca prim caracter in mesajul de commit) si
|
||||
**LF, nu CRLF** (`svn commit -F` refuza fisiere cu linii mixte CRLF/LF: `E135000`).
|
||||
@@ -11,11 +11,11 @@ Fisiere in `COMUN\utile\Teste\`: `vfp_ui_harness.ps1` (orchestrator generic, par
|
||||
`mock_amessagebox.prg` (mock dialog) — infrastructura sta in radacina `Teste\`; suitele stau in
|
||||
subfoldere pe subiect. Exemplu complet: `achizitie_import\test_import_nota_ui.prg` + `.ps1`.
|
||||
|
||||
**REGULA (Marius, 17/07/2026): testele pe aplicatii frontend exerseaza fluxul REAL al
|
||||
**REGULA (Marius): testele pe aplicatii frontend exerseaza fluxul REAL al
|
||||
utilizatorului** — formularul/butonul/metoda pe care o apeleaza aplicatia, NU introducerea
|
||||
directa a randurilor in cursoare/tabele. Popularea directa sare peste validari/filtre/efecte
|
||||
laterale si da PASS fals (caz real: un articol "adaugat" direct in cursor trecea testul, dar
|
||||
prin fluxul real nu se adauga deloc). Mock-urile raman permise doar pe INFRASTRUCTURA (Oracle,
|
||||
laterale si da PASS fals (caz real: articol "adaugat" direct in cursor trecea testul, dar prin
|
||||
fluxul real nu se adauga deloc). Mock-urile raman permise doar pe INFRASTRUCTURA (Oracle,
|
||||
dialoguri modale), nu pe pasii fluxului testat.
|
||||
|
||||
## Test UI nou in 5 pasi
|
||||
@@ -33,7 +33,57 @@ dialoguri modale), nu pe pasii fluxului testat.
|
||||
5. `powershell -File vfp_ui_harness.ps1 -TestPrg <test.prg> -Steps @('pas0',...)`.
|
||||
PNG-uri in `screenshots\step_<n>_<eticheta>.png`; log in `<test>_log.txt`.
|
||||
|
||||
## Capcane / deblocari (toate confirmate in sesiune)
|
||||
## Dialoguri modale (`Show(1)`)
|
||||
|
||||
Doua situatii, cu solutii diferite:
|
||||
|
||||
**A. Testul instantiaza el dialogul** — `WindowType = 0` inainte de `Show()` (pasul 3 de mai sus).
|
||||
`Show()` revine imediat si conduci formularul pas cu pas. Prefera intotdeauna varianta asta.
|
||||
|
||||
**B. `Show(1)` e hardcodat in metoda aplicatiei** (ex. `frm_facturare_articole.do_adauga_articol` /
|
||||
`do_modifica`): testul nu are referinta la dialog, deci nu poate seta `WindowType`, iar fluxul real
|
||||
cere sa treaca prin buton. Se conduce dintr-un **Timer pe `_SCREEN`**, pregatit INAINTE de actiunea
|
||||
care deschide dialogul:
|
||||
|
||||
1. `_SCREEN.AddObject('tmrDrv','Timer')`, `Interval = 200`,
|
||||
`BINDEVENT(_SCREEN.tmrDrv, 'Timer', <obiect driver>, 'Executa')`, `Enabled = .T.`
|
||||
2. `Show(1)` **chiar pompeaza mesaje Windows** cat e modal — timerul ticaie normal (masurat: 229
|
||||
tick-uri in 46s). Bucla modala nu e oarba la evenimente externe.
|
||||
3. **Detectia formularului: `_SCREEN.Forms(i)` / `_SCREEN.FormCount`**, potrivit pe `.Class`.
|
||||
**`_SCREEN.ActiveForm` NU merge headless** — a ramas gol la toate cele 229 de tick-uri: depinde
|
||||
de `WM_ACTIVATE`, care nu se declanseaza fara focus real, pe cand colectia `Forms` contine
|
||||
formularul indiferent de activare.
|
||||
4. **Referinta la controale**: `loForm.<nume>` merge normal; iterarea `loForm.Controls(i)` cu
|
||||
potrivire pe `.Name` e alternativa robusta (utila si ca diagnostic, pentru ca listeaza ce EXISTA
|
||||
cu adevarat). **Daca accesul da 1925 "Unknown member" pe un control care sigur e in clasa,
|
||||
suspecteaza mediul de test, nu colectia**: o eroare in constructia unui obiect adaugat mai
|
||||
devreme opreste adaugarea celor de dupa, iar formularul ramane incomplet fara sa se plange (caz
|
||||
real: lipsa cursorului `saft_taxtable`, capcana j, a lasat instanta cu 21 de controale in loc de
|
||||
25, iar controlul urmator din ordinea de adaugare "disparea"). Verifica intai `ControlCount` si
|
||||
lista de nume.
|
||||
5. **Inchiderea**: `do_termin()` (gateaza pe `inainte_de_do_termin()`, seteaza `gnButon = 1` si
|
||||
elibereaza — `_frm_base.vc2:363-371`) sau `do_renunt()`. **Daca validarea respinge, `do_termin()`
|
||||
nu seteaza `gnButon` si NU elibereaza formularul, deci `Show(1)` ramane blocat** — in testele
|
||||
care asteapta o respingere de validare, iesi prin `do_renunt()`.
|
||||
6. **Driverul se instrumenteaza obligatoriu**: log pe fiecare pas, `TRY/CATCH` cu
|
||||
`ErrorNo`/`Message`/`LineNo`, iar steagul "am tratat dialogul" se seteaza **dupa** interactiunea
|
||||
reusita, nu inainte. Altfel prima eroare e invizibila si blocheaza orice reincercare — simptomul
|
||||
e tick-uri la nesfarsit pana la timeout, fara nicio urma in log.
|
||||
|
||||
**Regula de metoda, invatata scump**: mediul unei suite noi se mosteneste din suita care **TRECE**,
|
||||
nu din una care esueaza. Un mediu copiat dintr-un test nevalidat a produs trei defecte succesive
|
||||
(cursor `saft_taxtable` lipsa, mock `poArticol` incomplet, nume de variabila coliziv), fiecare
|
||||
descoperit dupa cate o rulare, si toate aratau ca defecte de aplicatie sau ca "test agatat". Cand
|
||||
doua suite au nevoie de acelasi mediu, **extrage-l intr-un singur loc** (cu grija la capcana l
|
||||
pentru constructia obiectelor).
|
||||
|
||||
Doua non-dovezi, ca sa nu se piarda timp pe ele:
|
||||
- `AMEMBERS(a, o)` **fara flagul 2** intoarce proprietati/metode, **nu** obiectele continute —
|
||||
absenta unui control din acea lista nu inseamna ca lipseste din clasa.
|
||||
- `==` pe doua obiecte da eroare **107** "Operator/operand type mismatch"; pentru identitate se
|
||||
foloseste `COMPOBJ()`.
|
||||
|
||||
## Capcane / deblocari
|
||||
|
||||
a. **`SET SAFETY OFF` + `SET TALK OFF` inaintea primului `STRTOFILE`.** Cu SAFETY ON, scrierea
|
||||
log-ului existent scoate un dialog modal care blocheaza rularea (proces viu, "instanta
|
||||
@@ -46,23 +96,25 @@ c. **Asteptarea `ready_0`**: cu `.fxp` cald START apare in ~2s, la rece mult mai
|
||||
classlib-uri). `-ReadyTimeoutSec` generos (implicit 180s); retry NUMAI la "start ratat",
|
||||
nu la "start lent". Detectia "a pornit" se face pe mtime-ul log-ului > momentul lansarii
|
||||
(un log stale tinut de un vfp9 zombi pacaleste verificarea "log ne-gol") - omoara zombii
|
||||
inainte de fiecare lansare.
|
||||
PROPRII (filtrati pe linia de comanda, vezi punctul e) inainte de fiecare lansare.
|
||||
d. **`vfp9 -A test.prg` deschide INTERMITENT editorul** in loc sa ruleze (log gol). Lanseaza
|
||||
`.fxp`-ul PRECOMPILAT. Precompilarea (`COMPILE`+`QUIT`) atarna dupa COMPILE si, rulata in
|
||||
ACEEASI sesiune powershell, otraveste lansarile ulterioare - ruleaza-o intr-un proces copil
|
||||
izolat (`Start-Process -Wait _precompile.ps1`).
|
||||
e. **Suitele NU se ruleaza in paralel**: `_precompile.ps1` face `Get-Process vfp9 | Stop-Process
|
||||
-Force` (omoara toate instantele), deci un test lansat in paralel il ucide pe cel in curs.
|
||||
f. **FARA FURT DE FOCUS (17/07/2026)**: `Graphics.CopyFromScreen` fura focus si se corupe daca
|
||||
utilizatorul lucreaza in paralel - nu se mai foloseste. Capturile se fac cu `PrintWindow`
|
||||
(user32, P/Invoke) pe `Process.MainWindowHandle`, flag `2` = `PW_RENDERFULLCONTENT`
|
||||
(fallback `0` daca iese goala); merge cu fereastra acoperita, dar NU minimizata. Fereastra
|
||||
se muta OFF-SCREEN (`SetWindowPos`, `HWND_BOTTOM`, x=-4000, `SWP_NOACTIVATE`) imediat ce
|
||||
apare handle-ul si SE RE-IMPINGE la fiecare pas (VFP se reactiveaza singur la
|
||||
`Show()`/dialoguri). Consolele powershell copil sunt `-WindowStyle Hidden` (sigur pentru
|
||||
consola, NU pentru GUI VFP - ascunsa, `PrintWindow` poate reda gol). Implementat in
|
||||
`vfp_ui_harness.ps1` (Take-Screenshot, Push-Offscreen, Wait-MainWindowHandle) si
|
||||
`_precompile.ps1`.
|
||||
e. **Suitele NU se ruleaza in paralel**: harness-ul omoara instantele `vfp9` ramase inainte de
|
||||
fiecare lansare, deci un al doilea test pornit peste primul il ucide. Omorarea e filtrata pe
|
||||
linia de comanda (`Win32_Process.CommandLine` contine folderul de teste): instantele `vfp9`
|
||||
straine (sesiunea IDE a utilizatorului, teste dintr-un ALT proiect VFP) nu sunt atinse. Nu
|
||||
reintroduce `Get-Process vfp9 | Stop-Process -Force` fara filtru.
|
||||
f. **FARA FURT DE FOCUS**: `Graphics.CopyFromScreen` fura focus si se corupe daca
|
||||
utilizatorul lucreaza in paralel - nu se mai foloseste. Capturile: `PrintWindow` (user32,
|
||||
P/Invoke) pe `Process.MainWindowHandle`, flag `2` = `PW_RENDERFULLCONTENT` (fallback `0` daca
|
||||
iese goala); merge cu fereastra acoperita, NU minimizata. Fereastra se muta OFF-SCREEN
|
||||
(`SetWindowPos`, `HWND_BOTTOM`, x=-4000, `SWP_NOACTIVATE`) la aparitia handle-ului si SE
|
||||
RE-IMPINGE la fiecare pas (VFP se reactiveaza singur la `Show()`/dialoguri). Consolele
|
||||
powershell copil: `-WindowStyle Hidden` (sigur pentru consola, NU pentru GUI VFP ascunsa -
|
||||
`PrintWindow` poate reda gol). Implementat in `vfp_ui_harness.ps1` (Take-Screenshot,
|
||||
Push-Offscreen, Wait-MainWindowHandle) si `_precompile.ps1`.
|
||||
g. **Mock de messagebox**: `FUNCTION amessagebox` care returneaza direct valoarea butonului
|
||||
(6=Da), incarcat cu `SET PROCEDURE ... ADDITIVE` **PRIMUL**, inaintea fisierelor aplicatiei:
|
||||
la nume duplicat de procedura VFP foloseste fisierul cautat PRIMUL (verificat empiric).
|
||||
@@ -79,17 +131,84 @@ i. **Cursorii trebuie sa aiba EXACT indecsii creati de fluxul real** inainte de
|
||||
uneori in cascada la apeluri repetate. Verifica in codul apelant ce indecsi se creeaza si
|
||||
replica-i identic.
|
||||
j. **Mock-urile de date trebuie sa reproduca structura si semantica REALA a sursei** (view
|
||||
Oracle: toate coloanele; relatii intre randuri: toate randurile implicate, nu unul singur cu
|
||||
valori "compuse" manual in test). Un mock incomplet lasa campuri mereu NULL sau ascunde
|
||||
pasul care se testeaza. Cand un flag global activeaza cod suplimentar (ex. `gl406`), acel
|
||||
cod cere mock-uri in plus - verifica ce apeleaza si adauga metodele lipsa din dummy.
|
||||
Oracle: toate coloanele; relatii intre randuri: toate randurile implicate, nu una singura cu
|
||||
valori "compuse" manual). Un mock incomplet lasa campuri NULL sau ascunde pasul testat. Cand
|
||||
un flag global activeaza cod suplimentar (ex. `gl406`), acel cod cere mock-uri in plus -
|
||||
verifica ce apeleaza si adauga metodele lipsa din dummy. Cu `gl406=.T.` (SAFT),
|
||||
`GetTaxCodeIdPart`/`GetTaxCode` cer: `goApp.ReadIni`/`WriteIni` (clasa `dummyapp` are nevoie
|
||||
de METODE, nu doar proprietate), `goExecutor.oReset` (no-op e suficient), si cursor
|
||||
`saft_taxtable` real (nu doar mock pe `goExecutor` - `update_jtva_coloane` face
|
||||
`USE saft_taxtable` direct pe alias). Fara ele, simptomul e dialog nativ Windows "Open" (cauta
|
||||
`saft_taxtable.dbf`) care blocheaza headless la nesfarsit, fara linie noua in log si CPU 0% -
|
||||
vezi `depanare_testare_vfp.md` pentru diagnostic cu `EnumWindows`/`PrintWindow`. Acelasi
|
||||
simptom apare si FARA `gl406`: un control cu `RowSourceType=3` legat direct in clasa de un SQL
|
||||
pe `saft_taxtable` (ex. combo pe explicatie SAFT) isi evalueaza `RowSource` la constructia
|
||||
formularului indiferent de `gl406` sau de `Visible=.F.` - cursorul mock trebuie creat oricum.
|
||||
k. **`LOCATE FOR camp == 'literal'` pe camp `C(n)` padded nu gaseste nimic** (`==` e exact) -
|
||||
foloseste `ALLTRIM(camp) == 'literal'`.
|
||||
l. **`CREATEOBJECT`/`ADDPROPERTY` se comporta gresit apelate DINTR-O PROCEDURA in acest runtime
|
||||
headless** (obiect returnat ca string de 30 spatii; `ADDPROPERTY` da eroare 11). Din
|
||||
programul PRINCIPAL merg. Construieste obiectele-parametru INLINE in main, nu intr-un helper.
|
||||
(Cauza neclara; reproductibil.)
|
||||
headless** (obiect returnat ca string de 30 spatii; `ADDPROPERTY` da eroare 11). Din programul
|
||||
PRINCIPAL merg. Construieste obiectele-parametru INLINE in main, nu intr-un helper. Cauza
|
||||
confirmata intr-un caz concret: linie de cod prea lunga in ACEEASI metoda de clasa - vezi
|
||||
`depanare_testare_vfp.md` sectiunea 6; remediul (constructie inline) ramane valabil oricum.
|
||||
m. **Fara `SELECT-SQL` pe cursorul legat de grid**: `SELECT ... FROM <cursor> INTO CURSOR` cat
|
||||
timp cursorul e RecordSource-ul unui grid viu poate omori procesul vfp9 silentios (fara
|
||||
eroare catchabila, fara semafor). Foloseste xBase nativ (`COUNT FOR ... TO`, `CALCULATE`,
|
||||
`LOCATE`), care nu comuta zona de lucru a grid-ului.
|
||||
n. **Wrapper-ul `.ps1` trebuie sa paseze `-SyncDir` daca `.prg`-ul isi seteaza propriul
|
||||
`gcSyncDir`** - altfel testul scrie semafoarele intr-un folder si `vfp_ui_harness.ps1` le
|
||||
asteapta in cel implicit (`uisync\`), deadlock pana la timeout. Simptom identic cu "test
|
||||
agatat", dar FARA `.ERR` si cu CPU ~0 la procesul vfp9 (nu un dialog modal - procesul chiar
|
||||
asteapta un fisier care nu vine). Timeout minim: ~30s x numarul de pasi din `-Steps`
|
||||
(auto-continue per checkpoint din `HarnessWaitContinue`), plus marja de pornire.
|
||||
o. **Formularul resincronizeaza singur dupa o alegere din grid** (`lSyncPending` + `tmrSync`,
|
||||
ex. `do_modifica_explicatie_tva` din `ointroduceri.vcx`): starea imediat dupa actiune NU e
|
||||
observabila - `DOEVENTS FORCE` lasa timer-ul sa porneasca, iar resincronizarea rescrie ce
|
||||
tocmai s-a aplicat (la explicatia TVA: randul S revine la familia documentului, randurile T se
|
||||
realiniaza dupa el). Scrie assert-urile pe starea de DUPA resincronizare, pe un efect pe care
|
||||
resincronizarea NU il repara (acolo: `scc`-ul randului T, atins doar la schimbarea explicatiei)
|
||||
- altfel testul pica fara sa fie ceva gresit in cod.
|
||||
p. **Nu numi variabilele ca functii built-in VFP.** VFP e insensibil la litere mari/mici, iar la
|
||||
coliziune **functia castiga**. Caz real: `LOCAL loCk` pentru referinta la un checkbox se ciocneste
|
||||
cu `LOCK()` — `loCk.Value = 1` da eroarea **1924 "LOCK is not an object"**, iar `VARTYPE(loCk)`
|
||||
evalueaza `LOCK()` si intoarce `'L'`, deci verificarile de tipul `VARTYPE(lo...) == 'O'` ies
|
||||
**tacut false** si par sa spuna ca obiectul nu a fost gasit — masuratoarea e stricata, nu
|
||||
rezultatul. Simptom de recunoscut: mesajul de eroare contine numele **cu majuscule** al unei
|
||||
functii VFP, nu numele variabilei asa cum ai scris-o. Prefixeaza distinctiv (`loBifa`, `loCtrl`).
|
||||
q. **`DO ... WITH` paseaza PRIN REFERINTA, iar variabila devine invizibila sub numele ei propriu in
|
||||
procedura apelata.** Consecinta urata: orice `?variabila` din SQL passthrough de pe lantul
|
||||
apelurilor respective nu se mai poate lega, si VFP deschide dialogul nativ **"View Parameter —
|
||||
Enter the value for `<var>`"**, care blocheaza testul headless la infinit (fara log, fara
|
||||
eroare). Dovedit pe date: o variabila globala era valida in programul principal la fiecare
|
||||
checkpoint, dar `TYPE()` intorcea `'U'` (nedefinita) exact la intrarea in procedurile apelate cu
|
||||
`DO proc WITH gnAn, gnLuna` — si valida in cele apelate fara `DO ... WITH` — corelatie exacta cu
|
||||
**sintaxa apelului**, nu cu ce face procedura. Remediu: paranteze pe fiecare argument forteaza
|
||||
pasarea prin valoare — `DO proc WITH (gnAn), (gnLuna)`.
|
||||
r. **O suita care testeaza o clasa din `COMUN` poate incarca implicit copia ALTUI PRODUS**, daca
|
||||
harnessul de mediu comun (ex. `test_init_env_auto.prg`) face `SET DEFAULT TO`/`SET PATH` pe
|
||||
working copy-ul altui produs (ex. `D:\ROA\ROACONT\...`) inainte de `SET CLASSLIB TO <clasa>
|
||||
ADDITIVE`: `Createobject` gaseste prima clasa cu acel nume pe `PATH`, care poate fi
|
||||
`D:\ROA\ROACONT\COMUN\clase\<clasa>.vcx` in loc de fisierul editat sub test — silentios, fara
|
||||
eroare. Simptom: testul trece curat, dar valideaza cod vechi/alt working copy; orice concluzie
|
||||
trasa asa e nula. Remediu, dupa initializarea mediului comun: `RELEASE CLASSLIB <nume>` +
|
||||
`SET CLASSLIB TO <cale completa a fisierului sub test> ADDITIVE` (`SET CLASSLIB ... ADDITIVE`
|
||||
**singur**, fara `RELEASE` intai, da eroarea 24 "Alias name is already in use" si pastreaza
|
||||
tacut copia veche). Verificare obligatorie dupa instantiere: `loForm.ClassLibrary` trebuie sa
|
||||
arate calea completa asteptata.
|
||||
s. **Dialoguri native care nu apar in log si nu sunt prinse de `ON ERROR`/mock-uri** (ex. "View
|
||||
Parameter", "Open" pe fisier lipsa): nu se depaneaza orbeste, se ruleaza sub
|
||||
`COMUN\utile\Teste\watchdog_vfp.ps1 -Script <test.prg> -AutoDismiss`. Lanseaza `vfp9.exe -A -T`,
|
||||
polleaza ferestrele top-level ale procesului (identificate prin `Process.MainWindowHandle`, nu
|
||||
dupa numele clasei — VFP foloseste clase `vfp9...` si pentru shell-ul principal si pentru
|
||||
dialogurile proprii), captureaza PNG + textul fiecarui control copil (`WM_GETTEXT`) la orice
|
||||
fereastra noua, si omoara procesul la iesire (`finally`, niciodata ramas viu). **Interzis strict:
|
||||
input real** (`keybd_event`/`SetForegroundWindow`/`SendInput`/`mouse_event`) — masina e
|
||||
partajata, un input injectat la nivel de sistem ajunge in orice fereastra are focus in acel
|
||||
moment, nu neaparat in dialogul tintit (patit: un ESCAPE injectat a intrerupt sesiunea IDE a
|
||||
utilizatorului, aflat in lucru in paralel). `-AutoDismiss` foloseste STRICT mesaje Windows
|
||||
tintite pe handle (`BM_CLICK` pe buton Cancel/Anulare, altfel `WM_COMMAND IDCANCEL` ->
|
||||
ESCAPE ca mesaj `WM_KEYDOWN`/`WM_KEYUP` -> `WM_CLOSE`); pe dialogurile proprii VFP owner-drawn
|
||||
(butoane desenate, nu HWND-uri reale) dismiss-ul poate esua cinstit — captura PNG + dump text
|
||||
raman oricum de incredere, indiferent de rezultatul dismiss-ului. Sterge intotdeauna `.fxp`-ul
|
||||
vechi inainte de FIECARE rulare (watchdog-ul o face singur la lansare) — altfel VFP ruleaza
|
||||
tacut codul compilat vechi si rulari "identice" dau rezultate diferite, fara nicio urma in log.
|
||||
|
||||
@@ -14,16 +14,16 @@ Start-Process -FilePath "C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.e
|
||||
```
|
||||
|
||||
- Gate-ul de pornire (`gcNumeProgram = 'ROAGEST'` in `roagest.prg`) verifica
|
||||
`JUSTSTEM(SYS(16,0))` — numele programului de la nivelul 0 al stivei, nu numele
|
||||
procesului `.exe`. Rulat interpretat, `SYS(16,0)` = `roagest.prg`, deci gate-ul trece.
|
||||
`JUSTSTEM(SYS(16,0))` — numele programului de la nivelul 0 al stivei, nu numele procesului
|
||||
`.exe`. Rulat interpretat, `SYS(16,0)` = `roagest.prg`, deci gate-ul trece.
|
||||
- Fereastra rezultata are titlul `ROA - Gestiuni` (setat din `NUMEPROGRAM`).
|
||||
|
||||
## Capcana: focus furat de terminal
|
||||
|
||||
Daca sesiunea Claude Code afiseaza output in timp ce comanda de lansare ruleaza,
|
||||
fereastra terminalului/IDE-ului ramane in prim-plan si VFP porneste in fundal —
|
||||
`Screenshot`/`Snapshot` din `windows-mcp` pot raporta "No windows found" desi procesul
|
||||
si fereastra exista (verificabil cu `Get-Process vfp9 | Select MainWindowTitle`).
|
||||
Daca sesiunea Claude Code afiseaza output in timp ce comanda de lansare ruleaza, fereastra
|
||||
terminalului/IDE-ului ramane in prim-plan si VFP porneste in fundal — `Screenshot`/`Snapshot`
|
||||
din `windows-mcp` pot raporta "No windows found" desi procesul si fereastra exista (verificabil
|
||||
cu `Get-Process vfp9 | Select MainWindowTitle`).
|
||||
|
||||
Fix: inainte de screenshot, adu explicit fereastra in prim-plan dupa titlu:
|
||||
|
||||
@@ -31,8 +31,8 @@ Fix: inainte de screenshot, adu explicit fereastra in prim-plan dupa titlu:
|
||||
mcp__windows-mcp__App mode=switch name="ROA - Gestiuni"
|
||||
```
|
||||
|
||||
apoi `Screenshot`. Nu te baza pe enumerarea implicita de ferestre a `windows-mcp` cand
|
||||
ai lansat procesul chiar in runda curenta de comenzi.
|
||||
apoi `Screenshot`. Nu te baza pe enumerarea implicita de ferestre a `windows-mcp` cand ai lansat
|
||||
procesul chiar in runda curenta de comenzi.
|
||||
|
||||
## Curatare dupa test
|
||||
|
||||
|
||||
118
docs/tipuri_documente_facturare.md
Normal file
118
docs/tipuri_documente_facturare.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Tipurile de document din facturare (`VANZARI.TIP`) si seturile de contare (`ID_SET`)
|
||||
|
||||
Referinta pentru toata suita ROA: `PACK_FACTURARE` e in `COMUN`, iar `VANZARI.TIP` e citit de
|
||||
view-urile `FACT_VFACTURI` / `FACT_VFACTURI2`, de gridul principal de listare si de retiparire.
|
||||
|
||||
**Surse** (nu presupuneri):
|
||||
|
||||
- perechile `(lnIdSet, tnTip)` — comentariul din antetul `PACK_FACTURARE` (`:80-125` in exportul
|
||||
`all_source`), singurul loc care le documenteaza impreuna;
|
||||
- eticheta afisata — `CASE a.tip` din coloana `EXPLICATIE` a celor doua view-uri, citit din sursa
|
||||
live de pe `MARIUSM_AUTO` (06.08.2026);
|
||||
- restul — cod, marcat ca atare.
|
||||
|
||||
`ID_SET` e setul de formule contabile (`XSETS.ID_SET`, ajunge in `ACT.ID_SET`), pus in variabila de
|
||||
pachet `pack_facturare.nid_set` din `initializeaza_date_factura` (`:1864`). **Regula generala: setul
|
||||
"cu scadere din gestiune" e cel de baza + 10.**
|
||||
|
||||
## Facturi
|
||||
|
||||
| `ID_SET` | cu scadere | `TIP` | Document | `EXPLICATIE` afisat |
|
||||
|---|---|---|---|---|
|
||||
| 25000 | 25010 | 1 | pe baza de lista de preturi | `POLITICA PRETURI` |
|
||||
| 25001 | 25011 | 2 | pe baza de contracte | `CONTRACT` |
|
||||
| 25002 | 25012 | 3 | pe baza de comenzi | `COMANDA` |
|
||||
| 25003 | 25013 | 4 | pe baza de avize | `FACT. DIN AVIZ` |
|
||||
| 25004 | 25014 | 5 | lista de preturi in valuta | `POLITICA PRETURI - INVOICE` |
|
||||
| 25005 | 25015 | 6 | contract in valuta | `CONTRACT - VALUTA` |
|
||||
| 25006 | — | 7 | credit note | `CREDIT NOTE` |
|
||||
| 25007 | 25017 | 8 | retur factura in lei | `RETUR FACTURA IN LEI` |
|
||||
| 25008 | 25018 | 9 | retur factura in valuta | `RETUR INVOICE` |
|
||||
| 25009 | 25019 | 10 | factura fiscala in valuta | `POLITICA PRETURI - FACTURA VALUTA` |
|
||||
| 25042 | 25052 | 43 | bon fiscal (ROARETAIL, colectate de la magazine) | `BONURI FISCALE MAGAZINE` |
|
||||
| 25043 | — | 44 | factura hotel | `HOTEL` |
|
||||
| 25044 | 25054 | 45 | factura restaurant | `RESTAURANT` |
|
||||
| 25045 | 25055 | **46** | **nota de plata restaurant** | **nicio ramura** |
|
||||
| 25047 | 25057 | 48 | factura marfa custodie **cu** descarcare K | `FACT. CUSTODIE CU DESCARCARE PE BAZA DE K` |
|
||||
| 25048 | 25058 | 49 | factura marfa custodie **fara** descarcare K | `FACT. CUSTODIE FARA DESCARCARE PE BAZA DE K` |
|
||||
| 25051 | 25061 | 52 | pe baza de contract, factura fiscala in valuta | `CONTRACT - FACTURA VALUTA` |
|
||||
| 50100 | 25060 | 51 | factura ROAACNPRO | `COMERCIAL-FACTURARE` |
|
||||
|
||||
## Avize de expeditie
|
||||
|
||||
| `ID_SET` | cu scadere | `TIP` | Document | `EXPLICATIE` afisat |
|
||||
|---|---|---|---|---|
|
||||
| 25020 | 25030 | 21 | catre clienti, **din comanda** | `AVIZ PE BAZA DE COMANDA` |
|
||||
| 25021 | 25031 | 22 | catre clienti, din lista de preturi | `AVIZ DIN POLITICA DE PRETURI` |
|
||||
| 25022 | 25032 | 23 | transfer catre subunitati, din lista | `TRANSFER` |
|
||||
| 25023 | 25033 | 24 | aviz de retur | `AVIZ DE RETUR` |
|
||||
| 25024 | 25034 | 25 | transfer catre subunitati, **din comanda** | `TRANSFER PE BAZA DE COMANDA` |
|
||||
| 25025 | 25035 | 26 | catre clienti, din contract | `AVIZ PE BAZA DE CONTRACT` |
|
||||
| 25026 | 25036 | 27 | transfer catre subunitati, **pe baza de lucrare** | `TRANSFER PE BAZA DE LUCRARE` |
|
||||
| 25027 | 25037 | 28 | catre clienti debitori, **din comanda** | `CLIENTI DEBITORI - COMANDA` |
|
||||
| 25028 | 25038 | 29 | catre clienti debitori, din lista | `CLIENTI DEBITORI - POLITICA PRETURI` |
|
||||
| 25029 | 25039 | 30 | transfer catre subunitati, pe baza de NIR | `AVIZ PE BAZA DE NIR` |
|
||||
| 25040 | 25050 | 41 | retur transfer catre subunitati, lista de pret | `RETUR TRANSFER` |
|
||||
| 25041 | 25051 | 42 | catre clienti **custodie, din comanda** | `CLIENTI IN CUSTODIE - COMANDA` |
|
||||
| 25046 | 25056 | **47** | catre clienti **custodie, din comanda, pentru descarcare cu K** | `CLIENTI IN CUSTODIE - COMANDA (K)` |
|
||||
| 25049 | 25059 | 50 | *in lucru* — retur de la clienti custodie | nicio ramura |
|
||||
|
||||
## Tipuri negative
|
||||
|
||||
Nu apar in comentariul din pachet; luate din `CASE`-ul `EXPLICATIE`. Vin din alte produse sau din
|
||||
fluxuri valorice.
|
||||
|
||||
| `TIP` | `EXPLICATIE` afisat | Observatii |
|
||||
|---|---|---|
|
||||
| -1 | `MATERII PRIME SI MATERIALE` | |
|
||||
| -2 | `PRODUSE` | |
|
||||
| -3 | `MARFURI LA PRET DE ACHIZITIE` | |
|
||||
| -4 | `MARFURI LA PRET DE VANZARE` | |
|
||||
| -6 | `RETUR TRANSFER DIN GESTIUNE VALORICA` | ROAGEST; `ID_SET` 236/240/241/242 |
|
||||
| -7 | `AVIZ DE RETUR - VALORIC` | |
|
||||
| -8 | `FACTURA DE RETUR - VALORICA` | |
|
||||
| -9 | `PROTOCOL CU TVA - AVIZ EXPEDITIE` | |
|
||||
| -10 | `SPONSORIZARE - AVIZ EXPEDITIE` | |
|
||||
| -11 | `MARFURI LA PRET DE ACHIZITIE *` | |
|
||||
| -12 | `DEVIZE AUTO` | **ROAAUTO**, `factureaza_deviz` din `oproceduri_devize.prg` |
|
||||
| -13 | `RETUR MARFA IN CUSTODIE` | |
|
||||
|
||||
## Seturile de tipuri folosite in cod (unde conteaza incadrarea)
|
||||
|
||||
| Set | Unde | Ce face |
|
||||
|---|---|---|
|
||||
| `{3, 21, 28, 42, 47}` | `initializeaza_date_factura` (`:1888-1894`) | populeaza `pack_facturare.nid_comanda` din `clistaid` |
|
||||
| `+ {27}` | `scrie_avize_lucrare:5859` | suprascrie `nid_comanda` prin cursor pe `COMENZI` legat de `ID_LUCRARE` |
|
||||
| `{3, 21, 27, 28, 42, 46}` | `ALTELE` in ambele view-uri | afiseaza **comanda** (`nr_comanda/data`) |
|
||||
| `{4, 24, 8, 9}` | `ALTELE` in ambele view-uri | afiseaza **avizul** |
|
||||
| `{23, 25, 27, 30, 41, -6}` | `CLIENT` in ambele view-uri | afiseaza gestiunea, nu partenerul |
|
||||
| `{23, 25, 27, 30, 41}` si `-6` | `scrie_in_vanzari` (disc `:13530-13540`) | `lnIdGestiune` explicit, nu `min()` din detalii |
|
||||
|
||||
## Capcane confirmate
|
||||
|
||||
1. **`46` vs `47` in `ALTELE`.** Lista din view contine `46` (nota de plata restaurant, document
|
||||
care n-are comanda) si **nu contine** `47` (aviz custodie din comanda, care are). Pachetul
|
||||
populeaza `nid_comanda` pentru `47`, nu pentru `46`. `CASE`-ul `EXPLICATIE` din acelasi view are
|
||||
ramura pentru `47` si **nu** are pentru `46` — deci cele doua `CASE`-uri din acelasi view se
|
||||
contrazic pe aceste doua cifre. Decizia lui Marius (06.08.2026): **se adauga `47`, `46` ramane
|
||||
asa cum a fost scris.**
|
||||
2. **Efect vizibil pe `46`, azi**: ramura fiind luata fara ca documentul sa aiba comanda,
|
||||
`f.nr_comanda || '/' || to_char(f.data_comanda, ...)` da un **`/`** singur in coloana "Altele",
|
||||
nu gol. Nu s-a observat pe date pentru ca niciun client verificat nu foloseste modulul de
|
||||
restaurant (0 documente `tip=46` si pe `MARIUSM_AUTO`, si pe `VENDING`).
|
||||
3. **`ID_SET` 25051 apare de doua ori** in comentariul din pachet: ca set "cu scadere" pentru
|
||||
`tip=42` si ca set de baza pentru `tip=52`. Coliziune in documentatie, neverificata pe
|
||||
`XSETS` — de lamurit inainte de a te baza pe ea.
|
||||
4. **`tip=51`**: comentariul spune "factura ROAACNPRO", eticheta afisata e `COMERCIAL-FACTURARE`.
|
||||
Acelasi lucru, doua denumiri; eticheta din view e cea confirmata de constantele VFP curente
|
||||
(`ofacturare_comun.vc2:3654,3657`).
|
||||
5. **`tip=50`** e marcat "in lucru" in comentariu si n-are ramura de eticheta — de tratat ca
|
||||
neterminat, nu ca tip valid.
|
||||
6. **Comentariul nu e cod.** E singura documentare a perechilor `(ID_SET, TIP)`, dar poate fi ramas
|
||||
in urma. Inainte de a te baza pe o linie din el pentru o modificare, confirm-o pe cod
|
||||
(`initializeaza_date_factura`, `CASE`-urile din view-uri) sau pe `XSETS`.
|
||||
|
||||
## Legaturi
|
||||
|
||||
- `scripturi-migrare-db.md` — sursa de referinta pentru DDL e `MARIUSM_AUTO`, nu o schema de client.
|
||||
- `conventie_null_vfp.md` — `TIP_INCASARE` si celelalte coloane `0` vs `NULL` din view-uri.
|
||||
BIN
docs/todos-articole-preturi-saga.png
Normal file
BIN
docs/todos-articole-preturi-saga.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
55
docs/todos.txt
Normal file
55
docs/todos.txt
Normal file
@@ -0,0 +1,55 @@
|
||||
DONE 1. ROACONT. verificarea codurilor fiscale pe ANAF sa foloseasta istoricul de verificari drept cache 1 luna, in loc sa verifice mereu pe anaf. DE FAPT VREAU VERIFICARE ANAF CARE ACTUALIZEAZA SI CACHE, SI DACA NU MERGE ANAF, SA FOLOSEASCA CACHE
|
||||
|
||||
Vreau acelasi sistem de cache si pentru Registrul TVA la incasare care acum se descarca in schema comuna de baza de date CONTAFIN_ORACLE, pe serverul de baza de date, arhive zip de la anaf si se actualizeaza tabelele de rtvai_*
|
||||
Poate folosesti exact datele de la anaf descarcate pentru verificarea codurilor fiscale, in cazul in care exista informatia.
|
||||
|
||||
Vreau ca verificarile de coduri fiscale din D406, D394, Registrele de TVA sa foloseasca direct ANAF, si sa actualizeze cache-ul istoricul din baza de date (ISTORIC_CODURI_FISCALE)
|
||||
|
||||
DONE 2. ROACONT - Borderou eFactura, checkbox-urile diferente fata de Registrele de TVA sa aiba in caption si numarul de inregistrari cu diferente, astfel incat utilizatorul sa stie daca este cazul sa filtreze pentru afisarea facturilor cu diferente
|
||||
|
||||
DONE 3. ROACONT - modificare nota, explicatia tva sa filtreze dupa procent tva din tabel, ca sa arate o selectie mai mica de explicatii tva. vezi cum ai facut la explicatia tva din ointroduceri.vcx > import_nota.
|
||||
|
||||
DONE 4. ROACONT - overificari.vcx > formularul istoric coduri fiscale are coloane care nu mai au relavanta sau nu mai sunt completate din tabel. in tabelul contafin_oracle.istoric_coduri_fiscale, campul regcom are spatii si nu se afiseaza in formularul istoric. verifica
|
||||
|
||||
DONE 5. ROACONT - VERIFICARE cod fiscal, label-ul de sub grid-ul cu rezultate si detalii F4 sa contina si status "TVA Incasare"
|
||||
|
||||
6. ROAFACTURARE - EDITARE FACTURA EMISA ANTERIOR, CARE NU A FOST TRIMISA INCA IN EFACTURA (anaf_efactura.id_fact). punctul critic este ca notele contabile si eventual rulajele generate se genereaza complicat la emiterea facturii prin pack_facturare, iar editarea este o simpla editare, si nu sincronizeaza si notele contabile si rulajele. si sunt diverse tipuri de facturi sau de avize (pe baza de lista de preturi, pe baza de comanda, pe baza de contract, pe baza de aviz) si fiecare genereaza note contabile sau rulaje si articole de vanzare (vanzari si vanzari_detalii)
|
||||
|
||||
7. ROAFACTURARE - TVA unitar si valoarea TVA pe o linie de articol este calculata si nu salvata in vanzari si vanzari_detalii. din aceasta cauza, daca o factura are valoare totala 99.99 lei, dar utilizatorul doreste 100.00 lei total cu tva (pentru ca politica de preturi are bifat preturi fara TVA si se porneste calculul incepand de la pretul fara TVA al articolului) tva-ul se calculeaza rotunjit si nu se poate edita, ca sa dea factura fix 100.00 lei. implicatiile calculului TVA in loc de salvare sunt foarte mari si adanci in program, la introducerea facturii, listarea facturii initiale, relistarea facturii
|
||||
Sau de fapt este posibil sa poata utilizatorul sa modifice "preturi_cu_tva" la nivel de fiecare articol, la introducerea facturii si ulterior la editare factura, tocmai pentru ca utilizatorul doreste sa ajusteze tva-ul total pentru ca are restrictie sa dea facturii o valoare totala rotunjita, si se poate ajusta exact din pretul cu tva individual. pret_cu_tva se salveaza in vanzari_detalii pe fiecare articol.
|
||||
|
||||
DONE 8. ROAFACTURARE - in pack_facturare am salvat in vanzari valori totale denormalizat (fara tva, tva, cu tva, numarul avizului/comanda/contract etc.) ca sa nu le calculez in view din vanzari_detalii pentru ca view-ul de facturi este foarte complex, cu functii si expresii si nu era optimizabil si acceseaza total tabelele vanzari si vanzari_detalii. folosesc un view pe modelul original, si un view cu valorile totale din vanzari. doar ca am observat un bug, la facturile din avize, nu se salveaza corect in vanzari avizul sau numarul/data/suma chitantei daca factura este achitata numerar. trebuie depanat. schema de verificare productie este VENDING@ROA_VENDING
|
||||
|
||||
DONE 9. ROAGEST - MODIFICARE REGISTRU JURNAL - SA SE POATA MODIFICA SI "NNIR" in notele contabile si sincronizat in rulajele asociate. nu exista coloana NNIR in formularul de editare.
|
||||
|
||||
10. ROAFACTURARE - Integrare pagina contracte si rapoarte contracte in ROAFACTURARE, similar COMENZI in ROAFACTURARE - facturare pe baza de comenzi/contracte. trebuie comasate si drepturile pe obiectele din roacontracte cu obiectele noi din ROAFACTURARE.
|
||||
|
||||
11. ROAFACTURARE - Integrare politici de preturi in ROAFACTURARE - sunt numai editari de liste de preturi, note contabile, nomenclator articole, drepturi pe liste de preturi, care toate se folosesc numai in programul ROAFACTURARE
|
||||
|
||||
12. ROAFACTURARE - sa pot sa folosesc direct nomenclatorul de articole pe post de lista de preturi, sa nu mai definesc liste de preturi, note contabile asociate. Acum am un echivalent (lista de articole din stoc ca o lista de preturi virtuala)
|
||||
|
||||
Ca sa vand un articol, trebuie sa il introduc in nomenclatorul de articole obligatoriu. Acum trebuie sa il introduc si intr-o lista de preturi, ca sa am valuta, nota contabila de vanzare si daca are pret_cu_tva sau nu, procentul de tva vanzare, si bineinteles, pretul.
|
||||
|
||||
Am vazut la SAGA (alt ERP popular) ca in nomenclatorul de articole au cateva coloane de multe preturi, probabil pentru mai multe liste de preturi (todos-articole-preturi-saga.png)
|
||||
|
||||
Ideea este sa se poata face configurarea mult mai repede, eficient, dintr-un singur loc, ca sa se poata face factura mai rapid. Acum este nevoie de mult suport tehnic/instructaj si configurari pana se ajunge la facturare, si daca apare un articol diferit (ex: vanzare auto, in loc de marfa in mod normal), trebuie creata o politica noua de preturi, ca sa ii spun ce nota contabila de vanzare (4111 = 7xx) sa aiba aiba articolul respectiv.
|
||||
|
||||
13. ROAFACTURARE - FORMULARUL DE FACTURARE SA INCLUDA SI FORMULARUL DATE_FACTURA/DATE_AVIZ ETC. SI SA NU MAI INCARCE DE PE SERVER TOATE ARTICOLELE DIN TOATE POLITICELE DE PRETURI - INTRUCAT ESTE POSIBIL SA FIE SI MII DE ARTICOLE SI DUREAZA MULT SA LE ADUCA DE PE SERVER. AM INCEPUT DEJA MAI DEMULT UN FORMULAR UNIFICAT frm_facturare_articole2, DAR ERA MULT DE INTEGRAT DIN FORMULARUL VECHI.
|
||||
FRONTEND SIMILAR PE CARE IL DORESC ESTE IN ROAACPRO > FACTURA, SAU IN IMPORTUL DE EFACTURA, IN CARE AM INTEGRAT DATELE FACTURI, DOAR CA FACTURAREA DIN ROAFACTURARE ESTE MAI COMPLEXA - ESTE FOLOSITA SI PENTRU POLITICI DE PRETURI SI PENTRU CONTRACT/COMANDA/AVIZ/RETUR ETC.
|
||||
INTERESUL MEU ESTE SA SIMPLIFIC INTERFATA, SA FIE MAI EFICIENTA, SA NU FIE 2 FORMULARE PENTRU FACTURA, SA FAC MAI RAPID. in plus vreau si editare factura/aviz in toate variantele (politici preturi, comanda, contract, aviz etc) prin regenerare, adica sa arate formularul completat ca si cum ar fi inainte de salvarea initiala, ca sa pot sa fac editari ca si cum as fi la introducerea initiala - bineinteles cu stergerea facturii initiale (sters = 1) si salvarea celei noi, pentru a se vedea ce s-a modificat
|
||||
|
||||
14. ROACONT - efactura se salveaza xml detaliat si xml zip efactura si ocupa mult spatiu. vreau sa stiu cand nu mai este nevoie de xml detaliat si daca se poate curata tabelul ca sa nu mai ocupe spatiu, cel putin pentru facturi mai vechi. este important zip pentru ca este factura originala anaf.
|
||||
|
||||
15. ROACONT - ce locuri din program mai folosesc frm_modific2007 in loc de frm_modific2024. trebuie migrat la formularul mai nou.
|
||||
|
||||
16. ROAFACTURARE - in date_factura/date_aviz etc, la finalizare se verifica cursul valutar necesar pentru politicile de preturi care se factureaza. la revenire din formularul de curs valutar, focusul revine inainte de numar document, cred ca pe TIP DOCUMENT, si la iesire din serie se regenereaza numar act, ceea ce este periculos daca utilizatorul l-a schimbat si se modifica automat.
|
||||
|
||||
17. ROAFACTURARE - daca o nota contabile de vanzare nu are configurat tip de venit/cheltuiala, si nici articolele din lista de preturi, si nici nu se completeaza tip venit/cheltuiala la facturare, la finalizarea facturii apare o eroare oracle ORA ca id_venchelt nu are voie sa fie null. eroarea nu este user friendly si nu se poate recupera usor, pentru ca trebuie sa se dea renunt la toata factura si sa se reia tot porcesul, cu completarea tip venit cheltuiala. si nici nu stiu de ce este obligatoriu tip venit/cheltuiala.
|
||||
|
||||
18. ROAFACTURARE - EMITERE FACTURA DIN PROFORMA
|
||||
|
||||
19. ROAFACTURARE - EDITARE PROFORMA
|
||||
|
||||
20. ROAFACTURARE - FACTURA DIN COMANDA, COMANDA SE CONSIDERA FACTURATA DACA EXISTA FACTURI CU ACELEASI CANTITATI. AS VREA SA PUN MARKER DE FACTURAT PE COMANDA, CA SA NU MAI CAUT FACTURI - ESTE COSTISITOR. DOAR CA TREBUIE SA FII ATENT CA O COMANDA SE POATE FACTURA TOTAL/PARTIAL, SAU DIN MAI MULTE FACTURI, SAU SE POATE INCHIDE FORTAT. ACUM INCHIDEREA FORTATA ADAUGA CANTITATI NEGATIVE PE COMANDA, CA SA FACA CANTITATILE NEFACTURATE ZERO.
|
||||
|
||||
21. ROACONT - in formularul de verificare coduri fiscale, ar trebui sa fie si perioadele de tva, tva incasare, inactivitate, la fel ca in istoric, pentru ca utilizatorul sa nu mai caute altundeva. de asemenea, in messagebox pentru verificarea automata pe ANAF individuala ar trebui sa fie toate aceste informatii. sa se poata edita partenerul din formularul de verificare coduri fiscale prin dublu-click pe numele/codul fiscal al partenerului, similar cu formularul saft.
|
||||
@@ -892,6 +892,9 @@ DEFINE CLASS form1 AS form
|
||||
Go Top
|
||||
llNotaNoua = .T.
|
||||
llMaximize = .T.
|
||||
IF "OFACTURARE_EDITARE" $ Upper(Set("Procedure"))
|
||||
PregatesteArticoleFacturaEditare('tact')
|
||||
ENDIF
|
||||
loForm = Createobject([frm_modific2024], m.lnIdSet, m.llNotaNoua)
|
||||
loForm.lb_titlu_alb_b121.Caption = 'Initializare solduri'
|
||||
Select tact
|
||||
@@ -931,6 +934,7 @@ DEFINE CLASS form1 AS form
|
||||
Use In (Select('rul_temp'))
|
||||
Use In (Select('trul_obinv'))
|
||||
Use In (Select('rul_temp_obinv'))
|
||||
Use In (Select('crsArticoleFactura'))
|
||||
USE IN (SELECT('crsJtvaTemp'))
|
||||
|
||||
|
||||
|
||||
@@ -1800,6 +1800,9 @@ DEFINE CLASS form1 AS form
|
||||
Go Top
|
||||
llNotaNoua = .T.
|
||||
llMaximize = .T.
|
||||
IF "OFACTURARE_EDITARE" $ Upper(Set("Procedure"))
|
||||
PregatesteArticoleFacturaEditare('tact')
|
||||
ENDIF
|
||||
loForm = Createobject([frm_modific2024], m.lnIdSet, m.llNotaNoua)
|
||||
loForm.lb_titlu_alb_b121.Caption = 'Initializare solduri'
|
||||
Select tact
|
||||
@@ -1840,6 +1843,7 @@ DEFINE CLASS form1 AS form
|
||||
Use In (Select('rul_temp'))
|
||||
Use In (Select('trul_obinv'))
|
||||
Use In (Select('rul_temp_obinv'))
|
||||
Use In (Select('crsArticoleFactura'))
|
||||
USE IN (SELECT('crsJtvaTemp'))
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
*!* 28.07.2026
|
||||
*!* marius.mutu
|
||||
*!* vizeFactura, facturi primite: diferenta ignora TVA-ul de taxare inversa (jtva_ti)
|
||||
*!* vizeFactura: potrivirea cu registrul se face dupa numarul facturii ca grup complet de cifre din xnumar_act (comparat cu nract prin apartenenta, ca sa poata folosi indexul), cu rezerva pe suma egala doar pentru facturile in RON, codul fiscal normalizat pe ambele parti; diferenta ramane goala cand factura nu e in registru sau e in valuta
|
||||
|
||||
*********************************
|
||||
* Se apeleaza din ROACONT > Borderou eFactura
|
||||
@@ -2871,10 +2871,10 @@ Define Class ANAFeFactura As Custom
|
||||
* FACTURI PRIMITE
|
||||
lcData1 = '01' + PADL(INT(m.gnLuna),2,'0') + ALLTRIM(STR(m.gnAn))
|
||||
Text To lcSchema Noshow
|
||||
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), id_incarcare C(36), id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_tva_ron N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4), descriere M null, detalii_plata M null, diferenta N(16,4), procesat N(1), tip_persoana N(1) null, descarcat N(1) null, filepath c(250) null, procesat_server N(1) null, creditnote N(1)
|
||||
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), id_incarcare C(36), id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_tva_ron N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4) null, descriere M null, detalii_plata M null, diferenta N(16,4) null, procesat N(1), tip_persoana N(1) null, descarcat N(1) null, filepath c(250) null, procesat_server N(1) null, creditnote N(1)
|
||||
Endtext
|
||||
Text To lcSelect Noshow
|
||||
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, id_incarcare, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, total_fara_tva, total_tva, total_tva_ron, total_cu_tva, discount_fara_tva, taxe_fara_tva, valoare_fara_tva, total_de_plata, nume_valuta, test, jtotctva, descriere, detalii_plata, decode(creditnote,0,1,-1) * NVL(total_cu_tva, 0.00)-(NVL(jtotctva, 0.00)-NVL(jtva_ti, 0.00)) as diferenta, procesat, tip_persoana, descarcat, filepath, procesat_server, creditnote FROM anaf_vefactura_primit
|
||||
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, id_incarcare, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, total_fara_tva, total_tva, total_tva_ron, total_cu_tva, discount_fara_tva, taxe_fara_tva, valoare_fara_tva, total_de_plata, nume_valuta, test, jtotctva, descriere, detalii_plata, case when jtotctva is null then null when NVL(nume_valuta,'RON') <> 'RON' then null else decode(creditnote,0,1,-1) * NVL(total_cu_tva, 0.00)-(NVL(jtotctva, 0.00)-NVL(jtva_ti, 0.00)) end as diferenta, procesat, tip_persoana, descarcat, filepath, procesat_server, creditnote FROM anaf_vefactura_primit
|
||||
Endtext
|
||||
lcOrder = [data_act,numar_act,data_raspuns]
|
||||
lcgroup = []
|
||||
@@ -2891,10 +2891,10 @@ SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclien
|
||||
|
||||
* FACTURI TRIMISE
|
||||
Text To lcSchema Noshow
|
||||
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), id_incarcare C(36), id_descarcare c(36) null, mesaj_trimis C(250) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_tva_ron N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4), descriere M null, detalii_plata M null, diferenta N(16,4), procesat N(1), tip_persoana N(1) null, descarcat N(1) null, filepath c(250) null, procesat_server N(1) null, creditnote N(1)
|
||||
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), id_incarcare C(36), id_descarcare c(36) null, mesaj_trimis C(250) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_tva_ron N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4) null, descriere M null, detalii_plata M null, diferenta N(16,4) null, procesat N(1), tip_persoana N(1) null, descarcat N(1) null, filepath c(250) null, procesat_server N(1) null, creditnote N(1)
|
||||
Endtext
|
||||
Text To lcSelect Noshow
|
||||
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, id_incarcare, id_descarcare, mesaj_trimis, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, total_fara_tva, total_tva, total_tva_ron, total_cu_tva, discount_fara_tva, taxe_fara_tva, valoare_fara_tva, total_de_plata, nume_valuta, test, jtotctva, descriere, detalii_plata, decode(creditnote,0,1,-1) * NVL(total_cu_tva, 0.00)-NVL(jtotctva, 0.00) as diferenta, procesat, tip_persoana, descarcat, filepath, procesat_server, creditnote FROM anaf_vefactura_trimis
|
||||
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, id_incarcare, id_descarcare, mesaj_trimis, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, total_fara_tva, total_tva, total_tva_ron, total_cu_tva, discount_fara_tva, taxe_fara_tva, valoare_fara_tva, total_de_plata, nume_valuta, test, jtotctva, descriere, detalii_plata, case when jtotctva is null then null when NVL(nume_valuta,'RON') <> 'RON' then null else decode(creditnote,0,1,-1) * NVL(total_cu_tva, 0.00)-NVL(jtotctva, 0.00) end as diferenta, procesat, tip_persoana, descarcat, filepath, procesat_server, creditnote FROM anaf_vefactura_trimis
|
||||
Endtext
|
||||
lcOrder = [data_act,numar_act,data_trimis,data_raspuns]
|
||||
lcgroup = []
|
||||
@@ -2909,12 +2909,13 @@ SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclien
|
||||
Select crsFacturiTrimise
|
||||
Go Top
|
||||
|
||||
*!* diferenta ramane goala cand factura nu e in Registrul de Vanzari, ca la facturile primite/trimise
|
||||
* FACTURI EMISE
|
||||
Text To lcSchema Noshow
|
||||
ales N(1), id N(20), id_fact N(20), id_vanzare N(10), data_act D, numar_act N(14), in_valuta N(1) null, curs N(10,4) null, valval N(16,2), tvaval N(16,2),totval N(16,2), total_fara_tva N(16,2), total_tva N(16,2), total_cu_tva N(16,2), nume_valuta C(5) null, client C(100), id_client N(10), cod_fiscal C(30), tip_persoana N(1) null, trimis N(1) null, data_trimis T null, stare C(100) null, id_incarcare C(36) null, mesaj_trimis C(250) null, id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, xfurnizor C(200), xclient C(200), xdata_act D, xnumar_act C(30), xtotal_fara_tva N(16,4), xtotal_tva N(16,4), xtotal_tva_ron N(16,4), xtotal_cu_tva N(16,4), xdiscount_fara_tva N(16,4), xtaxe_fara_tva N(16,4), xvaloare_fara_tva N(16,4), xtotal_de_plata N(16,4), xnume_valuta C(5), test N(1) null, id_util N(10), utilizator C(100), jtotctva N(16,4), diferenta N(16,4), procesat N(1), procesat_server N(1), creditnote N(1)
|
||||
ales N(1), id N(20), id_fact N(20), id_vanzare N(10), data_act D, numar_act N(14), in_valuta N(1) null, curs N(10,4) null, valval N(16,2), tvaval N(16,2),totval N(16,2), total_fara_tva N(16,2), total_tva N(16,2), total_cu_tva N(16,2), nume_valuta C(5) null, client C(100), id_client N(10), cod_fiscal C(30), tip_persoana N(1) null, trimis N(1) null, data_trimis T null, stare C(100) null, id_incarcare C(36) null, mesaj_trimis C(250) null, id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, xfurnizor C(200), xclient C(200), xdata_act D, xnumar_act C(30), xtotal_fara_tva N(16,4), xtotal_tva N(16,4), xtotal_tva_ron N(16,4), xtotal_cu_tva N(16,4), xdiscount_fara_tva N(16,4), xtaxe_fara_tva N(16,4), xvaloare_fara_tva N(16,4), xtotal_de_plata N(16,4), xnume_valuta C(5), test N(1) null, id_util N(10), utilizator C(100), jtotctva N(16,4) null, diferenta N(16,4) null, procesat N(1), procesat_server N(1), creditnote N(1)
|
||||
Endtext
|
||||
Text To lcSelect Noshow
|
||||
SELECT 0 as ales, id, id_fact, id_vanzare, data_act, numar_act, in_valuta, curs, valval, tvaval, totval, total_fara_tva, total_tva,total_cu_tva, nume_valuta, client, id_client, cod_fiscal, NVL(tip_persoana,1) as tip_persoana, NVL(trimis,0) as trimis, data_trimis, stare, id_incarcare, mesaj_trimis, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, xfurnizor, xclient, xdata_act, xnumar_act, xtotal_fara_tva, xtotal_tva, xtotal_tva_ron, xtotal_cu_tva, xdiscount_fara_tva, xtaxe_fara_tva, xvaloare_fara_tva, xtotal_de_plata, xnume_valuta, test, id_util, utilizator, jtotctva, decode(creditnote,0,1,-1) * ROUND(NVL(xtotal_cu_tva , 0.00) * decode(in_valuta,1,curs,1), 2)-NVL(jtotctva, 0.00) as diferenta, procesat, procesat_server,creditnote FROM anaf_vefactura_emis
|
||||
SELECT 0 as ales, id, id_fact, id_vanzare, data_act, numar_act, in_valuta, curs, valval, tvaval, totval, total_fara_tva, total_tva,total_cu_tva, nume_valuta, client, id_client, cod_fiscal, NVL(tip_persoana,1) as tip_persoana, NVL(trimis,0) as trimis, data_trimis, stare, id_incarcare, mesaj_trimis, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, xfurnizor, xclient, xdata_act, xnumar_act, xtotal_fara_tva, xtotal_tva, xtotal_tva_ron, xtotal_cu_tva, xdiscount_fara_tva, xtaxe_fara_tva, xvaloare_fara_tva, xtotal_de_plata, xnume_valuta, test, id_util, utilizator, jtotctva, case when jtotctva is null then null else decode(creditnote,0,1,-1) * ROUND(NVL(xtotal_cu_tva , 0.00) * decode(in_valuta,1,curs,1), 2)-NVL(jtotctva, 0.00) end as diferenta, procesat, procesat_server,creditnote FROM anaf_vefactura_emis
|
||||
Endtext
|
||||
lcOrder = [data_act,numar_act]
|
||||
lcgroup = []
|
||||
|
||||
@@ -23,7 +23,7 @@ PROCEDURE vizImportEFactura
|
||||
|
||||
Private poFacturi, poFacturiDetalii
|
||||
Local loFrmFacturi As "frm_efactura_import", lcTip, llPrimite
|
||||
Local lcData1, lcFiltru, lcFiltruOriginal, lcOrder, lcSchema, lcgroup, llAfiseaza, llModParam
|
||||
Local lcData1, lcData2, lcFiltru, lcFiltruOriginal, lcOrder, lcSchema, lcgroup, ldData1, llAfiseaza, llModParam
|
||||
poFacturi = Null
|
||||
poFacturiDetalii = Null
|
||||
|
||||
@@ -34,12 +34,16 @@ PROCEDURE vizImportEFactura
|
||||
|
||||
* FACTURI PRIMITE/TRIMISE
|
||||
lcData1 = '01' + Padl(Int(m.gnLuna),2,'0') + Alltrim(Str(m.gnAn))
|
||||
*!* data_act pe interval (nu extract(year/month...)) ca sa poata folosi IDX_ANAF_EFACTURA_1(FACTURA_EMISA,XDATA_ACT,DATA_RASPUNS)
|
||||
ldData1 = GOMONTH(DATE(m.gnAn, m.gnLuna, 1), 1)
|
||||
lcData2 = '01' + PADL(MONTH(m.ldData1),2,'0') + ALLTRIM(STR(YEAR(m.ldData1)))
|
||||
TEXT To lcSchema Noshow
|
||||
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), partener C(200), id_incarcare C(36), id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal C(30) null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_tva_ron N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4), descriere M null, detalii_plata M null, diferenta N(16,4), procesat N(1), SerieActRoa V(10) Null, NrActRoa N(14) Null, IdPartRoa N(10) Null, PartenerRoa V(100) null, codFiscalROA V(20), idValutaROA N(5) null,numeValutaROA V(5) null, cursROA N(16,6) null,Cont c(4) Null,ACont c(4) Null,TVAIncasare N(1),Fdoc V(20) null,Id_Fdoc N(5) Null,Nrord V(100) null,Id_Lucrare I Null,Contract V(100) Null,Id_Ctr I Null,Sectie V(100) null,Id_Sectie I Null,dst_chlt V(100) null, Id_venchelt I NUll, nresp V(100) null, Id_responsabil I NUll , completat N(1), completatdet N(1), creditnote N(1), explicatiaROA V(100) null
|
||||
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), partener C(200), id_incarcare C(36), id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal C(30) null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_tva_ron N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4) null, descriere M null, detalii_plata M null, diferenta N(16,4) null, procesat N(1), SerieActRoa V(10) Null, NrActRoa N(14) Null, IdPartRoa N(10) Null, PartenerRoa V(100) null, codFiscalROA V(20), idValutaROA N(5) null,numeValutaROA V(5) null, cursROA N(16,6) null,Cont c(4) Null,ACont c(4) Null,TVAIncasare N(1),Fdoc V(20) null,Id_Fdoc N(5) Null,Nrord V(100) null,Id_Lucrare I Null,Contract V(100) Null,Id_Ctr I Null,Sectie V(100) null,Id_Sectie I Null,dst_chlt V(100) null, Id_venchelt I NUll, nresp V(100) null, Id_responsabil I NUll , completat N(1), completatdet N(1), creditnote N(1), explicatiaROA V(100) null
|
||||
ENDTEXT
|
||||
|
||||
*!* diferenta ramane goala cand factura nu e in Registrul TVA sau e in valuta si tine cont de semnul notei de credit, ca la borderou
|
||||
TEXT To lcSelect TEXTMERGE Noshow
|
||||
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, partener, id_incarcare, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, cod_fiscal, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, total_fara_tva, total_tva, total_tva_ron, total_cu_tva, discount_fara_tva, taxe_fara_tva, valoare_fara_tva, total_de_plata, nume_valuta, test, jtotctva, descriere, detalii_plata, NVL(total_cu_tva,0.00) - (NVL(jtotctva,0.00) - NVL(jtva_ti,0.00)) as diferenta, procesat,
|
||||
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, partener, id_incarcare, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, cod_fiscal, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, total_fara_tva, total_tva, total_tva_ron, total_cu_tva, discount_fara_tva, taxe_fara_tva, valoare_fara_tva, total_de_plata, nume_valuta, test, jtotctva, descriere, detalii_plata, case when jtotctva is null then null when NVL(nume_valuta,'RON') <> 'RON' then null else decode(creditnote,0,1,-1) * NVL(total_cu_tva,0.00) - (NVL(jtotctva,0.00) - NVL(jtva_ti,0.00)) end as diferenta, procesat,
|
||||
'' as SerieActRoa, CAST(null as Number(14)) as NrActRoa, CAST(null as Number(20)) as idPartRoa, '' as PartenerRoa, '' as codFiscalROA, CAST(null as Number(10)) as idValutaROA, '' as numeValutaROA, CAST(null as Number(16,6)) as cursROA,
|
||||
'' as Cont, '' as acont, 0 as TVAIncasare, '' as Fdoc, CAST(0 as Number(5)) as Id_Fdoc, '' as Nrord, CAST(0 as Number(10)) as id_Lucrare, '' as Contract, CAST(null as Number(10)) as id_ctr,
|
||||
'' Sectie, CAST(0 as Number(10)) as id_Sectie, '' as dst_chlt, CAST(0 as Number(10)) as id_Venchelt, '' as nresp, CAST(0 as Number(10)) as id_responsabil, 0 as completat, 0 as completatdet, creditnote, '' as explicatiaROA
|
||||
@@ -48,7 +52,7 @@ SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclien
|
||||
|
||||
lcOrder = [data_act,numar_act,data_raspuns]
|
||||
lcgroup = []
|
||||
lcFiltru = [(extract(year from data_act) = ?gnAn and extract(month from data_act) = ?gnLuna) or (data_act is null and data_raspuns >= to_date('] + m.lcData1 + [','ddmmyyyy'))]
|
||||
lcFiltru = [(data_act >= to_date('] + m.lcData1 + [','ddmmyyyy') and data_act < to_date('] + m.lcData2 + [','ddmmyyyy')) or (data_act is null and data_raspuns >= to_date('] + m.lcData1 + [','ddmmyyyy'))]
|
||||
lcFiltruOriginal = []
|
||||
llModParam = .T.
|
||||
llAfiseaza = .F.
|
||||
|
||||
@@ -56,6 +56,24 @@
|
||||
*!* inactiv sau perioada s-a incheiat deja; F4 arata intotdeauna perioada completa si mesajul primit
|
||||
*!* de la ANAF, inclusiv cand nu exista partener cu codul corect
|
||||
|
||||
*!* 28.07.2026
|
||||
*!* marius.mutu
|
||||
*!* optiunea de verificare ANAF arata separat setarea utilizatorului, setarea firmei, implicitul
|
||||
*!* programului si starea de pe calculator; utilizatorul isi poate sterge propria setare, ca sa revina
|
||||
*!* la setarea firmei sau la implicitul programului
|
||||
|
||||
*!* 30.07.2026
|
||||
*!* marius.mutu
|
||||
*!* verificare ANAF: cand serviciul e cazut sau apelul esueaza, verdictul se citeste din istoricul de
|
||||
*!* coduri fiscale (cache Oracle), daca istoricul are ceva proaspat; banda de stare si detaliile (F4)
|
||||
*!* arata atunci data verificarii citite din istoric, cu mentiune explicita cand ANAF e indisponibil;
|
||||
*!* ordinea de incercare ANAF/istoric e configurabila per firma
|
||||
|
||||
*!* 02.08.2026
|
||||
*!* marius.mutu
|
||||
*!* verificarea ANAF se poate cere si la caut_partener (parametri optionali de verificare
|
||||
*!* si de data a documentului), pentru achizitia de import si pentru schimbarea furnizorului pe rulaj
|
||||
|
||||
*!* #DEFINE CRLF CHR(13) + CHR(10)
|
||||
#INCLUDE COMUN\ROA.H
|
||||
|
||||
@@ -63,6 +81,7 @@ Procedure ANAF_StarePartener
|
||||
Lparameters tcCodFiscal, tdData, tlDoarCache, tlNecesitaApel, tlNegasit, tcClasaEsec, tnTipPersoana
|
||||
|
||||
Local lcCodFiscal, lcCui, loRezANAF, lcCheieCache, lnI, llValid, loOut, ldData, llNegasit, lcStareServiciu
|
||||
Local lcOrdine, loVerificareANAF As "VerificareANAF", lcSelectOrig
|
||||
|
||||
tlNecesitaApel = .F.
|
||||
tlNegasit = .F.
|
||||
@@ -108,29 +127,54 @@ Procedure ANAF_StarePartener
|
||||
Endif
|
||||
lcCheieCache = 'C' + m.lcCui + '_' + Dtos(m.ldData)
|
||||
If goCacheANAF_Sesiune.GetKey(m.lcCheieCache) = 0
|
||||
lcStareServiciu = ANAF_StareServiciu()
|
||||
Do Case
|
||||
Case m.lcStareServiciu == 'CAZUT'
|
||||
tlNecesitaApel = .F.
|
||||
tcClasaEsec = 'FARA_RASPUNS'
|
||||
Return .Null.
|
||||
Case m.lcStareServiciu == 'SE_TESTEAZA'
|
||||
tlNecesitaApel = .T.
|
||||
tcClasaEsec = 'SE_TESTEAZA'
|
||||
Return .Null.
|
||||
Endcase
|
||||
tlNecesitaApel = .T.
|
||||
If m.tlDoarCache
|
||||
Return .Null.
|
||||
*** ordinea ANAF/istoric (OPTIUNI.ANAFCACHEORDINE_UNIC, VerificareANAF.OrdineCache din validare.prg);
|
||||
*** implicit ANAF,CACHE - pe CACHE,ANAF se incearca intai istoricul, iar apelul ANAF se sare cand e proaspat
|
||||
lcOrdine = 'ANAF,CACHE'
|
||||
lcSelectOrig = Select()
|
||||
Try
|
||||
loVerificareANAF = Createobject("VerificareANAF")
|
||||
lcOrdine = loVerificareANAF.OrdineCache('UNIC')
|
||||
Catch
|
||||
Endtry
|
||||
If Select() <> m.lcSelectOrig And Used(m.lcSelectOrig)
|
||||
Select (m.lcSelectOrig)
|
||||
Endif
|
||||
If m.lcOrdine == 'CACHE,ANAF'
|
||||
loRezANAF = ANAF_CitesteDinIstoric(m.lcCui, m.ldData, 'CACHE')
|
||||
Endif
|
||||
If Vartype(m.loRezANAF) <> 'O'
|
||||
lcStareServiciu = ANAF_StareServiciu()
|
||||
Do Case
|
||||
Case m.lcStareServiciu == 'CAZUT'
|
||||
tlNecesitaApel = .F.
|
||||
tcClasaEsec = 'FARA_RASPUNS'
|
||||
*** plasa de siguranta: ANAF cazut - verdict din istoric, daca e proaspat, etichetat distinct
|
||||
loRezANAF = ANAF_CitesteDinIstoric(m.lcCui, m.ldData, 'CACHE_INDISP')
|
||||
If Vartype(m.loRezANAF) = 'O'
|
||||
tcClasaEsec = ''
|
||||
Endif
|
||||
Case m.lcStareServiciu == 'SE_TESTEAZA'
|
||||
tlNecesitaApel = .T.
|
||||
tcClasaEsec = 'SE_TESTEAZA'
|
||||
Otherwise
|
||||
tlNecesitaApel = .T.
|
||||
If !m.tlDoarCache
|
||||
llNegasit = .F.
|
||||
loRezANAF = ANAF_VerificaCuiSingle(m.lcCui, m.ldData, @llNegasit, @tcClasaEsec)
|
||||
Do Case
|
||||
Case m.tcClasaEsec == 'FARA_RASPUNS'
|
||||
ANAF_SeteazaStareServiciu('CAZUT', 'CUI=' + m.lcCui)
|
||||
*** plasa de siguranta: apelul a esuat - acelasi fallback pe istoric
|
||||
loRezANAF = ANAF_CitesteDinIstoric(m.lcCui, m.ldData, 'CACHE_INDISP')
|
||||
If Vartype(m.loRezANAF) = 'O'
|
||||
tcClasaEsec = ''
|
||||
Endif
|
||||
Case m.tcClasaEsec == ''
|
||||
ANAF_SeteazaStareServiciu('VIU', 'CUI=' + m.lcCui)
|
||||
Endcase
|
||||
Endif
|
||||
Endcase
|
||||
Endif
|
||||
llNegasit = .F.
|
||||
loRezANAF = ANAF_VerificaCuiSingle(m.lcCui, m.ldData, @llNegasit, @tcClasaEsec)
|
||||
Do Case
|
||||
Case m.tcClasaEsec == 'FARA_RASPUNS'
|
||||
ANAF_SeteazaStareServiciu('CAZUT', 'CUI=' + m.lcCui)
|
||||
Case m.tcClasaEsec == ''
|
||||
ANAF_SeteazaStareServiciu('VIU', 'CUI=' + m.lcCui)
|
||||
Endcase
|
||||
If Vartype(m.loRezANAF) = 'O'
|
||||
goCacheANAF_Sesiune.Add(m.loRezANAF, m.lcCheieCache)
|
||||
Endif
|
||||
@@ -153,10 +197,64 @@ Procedure ANAF_StarePartener
|
||||
Addproperty(loOut, "dSfarsitScpTVA", Iif(Pemstatus(loRezANAF, 'dSfarsitScpTVA', 5), Nvl(loRezANAF.dSfarsitScpTVA, {}), {}))
|
||||
Addproperty(loOut, "dAnulareScpTVA", Iif(Pemstatus(loRezANAF, 'dAnulareScpTVA', 5), Nvl(loRezANAF.dAnulareScpTVA, {}), {}))
|
||||
Addproperty(loOut, "cMesajScpTVA", Iif(Pemstatus(loRezANAF, 'cMesajScpTVA', 5), Alltrim(Nvl(loRezANAF.cMesajScpTVA, '')), ''))
|
||||
Addproperty(loOut, "lTvaIncasareANAF", Iif(Pemstatus(loRezANAF, 'lTvaIncasare', 5), Nvl(loRezANAF.lTvaIncasare, .F.), .F.))
|
||||
Addproperty(loOut, "dInceputTvaInc", Iif(Pemstatus(loRezANAF, 'dInceputTvaInc', 5), Nvl(loRezANAF.dInceputTvaInc, {}), {}))
|
||||
Addproperty(loOut, "dSfarsitTvaInc", Iif(Pemstatus(loRezANAF, 'dSfarsitTvaInc', 5), Nvl(loRezANAF.dSfarsitTvaInc, {}), {}))
|
||||
Addproperty(loOut, "dData", m.ldData)
|
||||
Addproperty(loOut, "cSursa", Iif(Pemstatus(loRezANAF, 'cSursa', 5), loRezANAF.cSursa, 'ANAF'))
|
||||
Addproperty(loOut, "dDataSursa", Iif(Pemstatus(loRezANAF, 'dDataSursa', 5), Nvl(loRezANAF.dDataSursa, {}), {}))
|
||||
Return loOut
|
||||
Endproc && ANAF_StarePartener
|
||||
|
||||
*************************************
|
||||
*** Citeste din ISTORIC_CODURI_FISCALE (VerificareANAF.CitesteIstoricPentruCoduri, validare.prg) verdictul
|
||||
*** cache pentru un singur CUI normalizat, daca e proaspat; tcSursa eticheteaza rezultatul ('CACHE' sau
|
||||
*** 'CACHE_INDISP'). Intoarce .NULL. cand istoricul nu are nimic proaspat pentru codul dat, fara eroare
|
||||
*************************************
|
||||
Procedure ANAF_CitesteDinIstoric
|
||||
Lparameters tcCui, tdData, tcSursa
|
||||
|
||||
Local loVerificareANAF As "VerificareANAF", lcAliasCache, loRez, lcSelectOrig
|
||||
loRez = .Null.
|
||||
lcAliasCache = 'crsANAFIstoricOcautare'
|
||||
lcSelectOrig = Select()
|
||||
Try
|
||||
Use In (Select(m.lcAliasCache))
|
||||
loVerificareANAF = Createobject("VerificareANAF")
|
||||
loVerificareANAF.CitesteIstoricPentruCoduri(m.tcCui, m.tdData, m.lcAliasCache)
|
||||
If Used(m.lcAliasCache) And Reccount(m.lcAliasCache) > 0
|
||||
Select (m.lcAliasCache)
|
||||
Go Top
|
||||
If !Empty(Nvl(denumire, ''))
|
||||
loRez = Createobject("Empty")
|
||||
Addproperty(loRez, "cui", cui)
|
||||
Addproperty(loRez, "scpTVA", Nvl(scpTVA, .F.))
|
||||
Addproperty(loRez, "statusInactivi", Nvl(statusInactivi, .F.))
|
||||
Addproperty(loRez, "denumire", Nvl(denumire, ""))
|
||||
Addproperty(loRez, "mesaj", Nvl(mesaj, ""))
|
||||
Addproperty(loRez, "dInceputScpTVA", Nvl(data_inceput_ScpTVA, {}))
|
||||
Addproperty(loRez, "dSfarsitScpTVA", Nvl(data_sfarsit_ScpTVA, {}))
|
||||
Addproperty(loRez, "dAnulareScpTVA", Nvl(data_anul_imp_ScpTVA, {}))
|
||||
Addproperty(loRez, "cMesajScpTVA", Nvl(mesaj_ScpTVA, ""))
|
||||
Addproperty(loRez, "lTvaIncasare", Nvl(statusTvaIncasare, .F.))
|
||||
Addproperty(loRez, "dInceputTvaInc", Nvl(dataInceputTvaInc, {}))
|
||||
Addproperty(loRez, "dSfarsitTvaInc", Nvl(dataSfarsitTvaInc, {}))
|
||||
Addproperty(loRez, "cSursa", m.tcSursa)
|
||||
Addproperty(loRez, "dDataSursa", Nvl(data_sursa, {}))
|
||||
Endif
|
||||
Endif
|
||||
Catch
|
||||
loRez = .Null.
|
||||
Endtry
|
||||
If Used(m.lcAliasCache)
|
||||
Use In (Select(m.lcAliasCache))
|
||||
Endif
|
||||
If Select() <> m.lcSelectOrig And Used(m.lcSelectOrig)
|
||||
Select (m.lcSelectOrig)
|
||||
Endif
|
||||
Return m.loRez
|
||||
Endproc && ANAF_CitesteDinIstoric
|
||||
|
||||
Procedure ANAF_StareServiciu
|
||||
If Type('gcANAF_StareServiciu') = 'U'
|
||||
Public gcANAF_StareServiciu, gtANAF_StareServiciuMoment, gnANAF_StareServiciuStamp
|
||||
@@ -335,7 +433,7 @@ Endproc && AplicaInlocuirePartenerANAF
|
||||
|
||||
Procedure ANAF_ComutaVerificare
|
||||
*** valori: 0 = oprit, 1 = starea pe randul curent, 3 = starea si confirmarea la partener discordant, 9 = oprit pe acest calculator
|
||||
Local lcSel, lcOptiune, lcEticheta, lcValIni, lcValUtil, lcValFirma, lcSursa, lnNivel, lnNou, lcMesaj
|
||||
Local lcSel, lcOptiune, lcEticheta, lcValIni, lcValUtil, lcValFirma, lcSursa, lnNivel, lnNou, lcMesaj, lnRasp
|
||||
|
||||
lcEticheta = 'Verificare ANAF la alegerea partenerului'
|
||||
lcOptiune = 'RC_ANAF_VERIF_SELECTIE'
|
||||
@@ -363,12 +461,22 @@ Procedure ANAF_ComutaVerificare
|
||||
|
||||
lcMesaj = 'Acum: ' + Transform(m.lnNivel) + ' - ' + ANAF_TextNivel(m.lnNivel) + Chr(13) + ;
|
||||
'(' + m.lcSursa + ')' + Chr(13) + Chr(13) + ;
|
||||
' Utilizatorul curent : ' + ANAF_TextSetare(m.lcValUtil) + Chr(13) + ;
|
||||
' Firma : ' + ANAF_TextSetare(m.lcValFirma) + Chr(13) + ;
|
||||
' Implicit program : 1 - ' + ANAF_TextNivel(1) + Chr(13) + ;
|
||||
' Acest calculator : ' + Iif(m.lcValIni == '0', 'verificare oprita', 'verificare pornita') + Chr(13) + Chr(13) + ;
|
||||
' 0 = ' + ANAF_TextNivel(0) + Chr(13) + ;
|
||||
' 1 = ' + ANAF_TextNivel(1) + Chr(13) + ;
|
||||
' 3 = ' + ANAF_TextNivel(3) + Chr(13) + ;
|
||||
' 9 = ' + ANAF_TextNivel(9) + Chr(13) + Chr(13) + ;
|
||||
'Valorile 0, 1 si 3 va urmaresc pe orice calculator.'
|
||||
If Amessagebox(m.lcMesaj + Chr(13) + Chr(13) + 'Modificati valoarea?', 4 + 32, lcEticheta) <> 6
|
||||
'Valorile 0, 1 si 3 va urmaresc pe orice calculator.' + Chr(13) + Chr(13) + ;
|
||||
'Da = aleg o valoare, Nu = revin la setarea firmei / implicita, Renunta = las asa'
|
||||
lnRasp = Amessagebox(m.lcMesaj, 3 + 32, m.lcEticheta)
|
||||
If m.lnRasp = 7
|
||||
ANAF_ReseteazaVerificare(m.lcOptiune, m.lcEticheta, m.lcValUtil, m.lcValFirma)
|
||||
Return
|
||||
Endif
|
||||
If m.lnRasp <> 6
|
||||
Return
|
||||
Endif
|
||||
lnNou = aInputBox('Valoarea noua (0, 1, 3 sau 9):', m.lcEticheta, Iif(m.lcValIni == '0', 9, m.lnNivel))
|
||||
@@ -395,6 +503,54 @@ Procedure ANAF_ComutaVerificare
|
||||
Endif
|
||||
Endproc && ANAF_ComutaVerificare
|
||||
|
||||
Procedure ANAF_ReseteazaVerificare
|
||||
Lparameters tcOptiune, tcEticheta, tcValUtil, tcValFirma
|
||||
|
||||
Local lnNivel
|
||||
If Empty(m.tcValUtil)
|
||||
Amessagebox('Nu exista o setare proprie de sters: se foloseste deja ' + ;
|
||||
Iif(Empty(m.tcValFirma), 'valoarea implicita a programului.', 'setarea firmei.'), 0 + 64, m.tcEticheta)
|
||||
Return
|
||||
Endif
|
||||
If !ANAF_StergeOptiuneUtilizator(m.tcOptiune)
|
||||
Return
|
||||
Endif
|
||||
If Type('goCacheANAF_Nivel') = 'O'
|
||||
Release goCacheANAF_Nivel
|
||||
Endif
|
||||
lnNivel = ANAF_NivelVerificare()
|
||||
Amessagebox('Acum: ' + Transform(m.lnNivel) + ' - ' + ANAF_TextNivel(m.lnNivel), 0 + 64, m.tcEticheta)
|
||||
Endproc && ANAF_ReseteazaVerificare
|
||||
|
||||
Procedure ANAF_StergeOptiuneUtilizator
|
||||
Lparameters tcOptiune
|
||||
|
||||
Local lcSel, lcSql, lnSucces
|
||||
lcSel = Select()
|
||||
lcSql = [DELETE FROM OPTIUNI_UTIL WHERE UPPER(VARNAME) = '] + Upper(Alltrim(m.tcOptiune)) + ;
|
||||
[' AND ID_UTIL = ] + Transform(gnIdUtil)
|
||||
lnSucces = goExecutor.oExecute(m.lcSql)
|
||||
If m.lnSucces < 0
|
||||
Amessagebox(goExecutor.cEroare, 0 + 16, 'Eroare')
|
||||
Select (m.lcSel)
|
||||
Return .F.
|
||||
Endif
|
||||
actualizeaza_optiuni_utilizator()
|
||||
Select (m.lcSel)
|
||||
Return .T.
|
||||
Endproc && ANAF_StergeOptiuneUtilizator
|
||||
|
||||
Procedure ANAF_TextSetare
|
||||
Lparameters tcVal
|
||||
|
||||
Local lnNivel
|
||||
If Empty(Nvl(m.tcVal, ''))
|
||||
Return 'nesetata'
|
||||
Endif
|
||||
lnNivel = Int(Val(m.tcVal))
|
||||
Return Transform(m.lnNivel) + ' - ' + ANAF_TextNivel(m.lnNivel)
|
||||
Endproc && ANAF_TextSetare
|
||||
|
||||
Procedure ANAF_TextNivel
|
||||
Lparameters tnNivel
|
||||
Do Case
|
||||
@@ -694,7 +850,7 @@ DEFINE CLASS anaf_verif_cautare AS Custom
|
||||
|
||||
PROCEDURE TextStare
|
||||
Lparameters toStare, tcPerioada
|
||||
Return Iif(toStare.lPlatitorANAF, 'Platitor TVA', 'Neplatitor TVA') + Nvl(m.tcPerioada, '') + Iif(toStare.lInactivANAF, ', Inactiv', '')
|
||||
Return Iif(toStare.lPlatitorANAF, 'Platitor TVA', 'Neplatitor TVA') + Nvl(m.tcPerioada, '') + Iif(toStare.lInactivANAF, ', Inactiv', '') + Iif(toStare.lTvaIncasareANAF, ', TVA la incasare', '')
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE SufixPerioadaTVA
|
||||
@@ -725,7 +881,26 @@ DEFINE CLASS anaf_verif_cautare AS Custom
|
||||
lcPerioada = This.SufixPerioadaTVA(toStare)
|
||||
Return 'ANAF: ' + This.TextStare(toStare, m.lcPerioada) + ' (' + ;
|
||||
Iif(Empty(m.lcDenANAF), '', m.lcDenANAF + Iif(m.tlCuVirgula, ', ', ' ')) + m.lcCodOk + ')' + ;
|
||||
Iif(Empty(m.lcPerioada), ' la ' + Dtoc(toStare.dData), '')
|
||||
Iif(Empty(m.lcPerioada), ' la ' + Dtoc(toStare.dData), '') + ;
|
||||
This.SufixSursa(toStare)
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE SufixSursa
|
||||
Lparameters toStare
|
||||
*** eticheteaza verdictele care nu vin dintr-un raspuns ANAF proaspat, ci din istoricul cache (contract 4.5)
|
||||
If !Pemstatus(m.toStare, 'cSursa', 5)
|
||||
Return ''
|
||||
Endif
|
||||
*!* 01.08.2026 marius.mutu: marcaj explicit al sursei, la fel ca in grid si in dialogul de verificare
|
||||
Do Case
|
||||
Case toStare.cSursa == 'ANAF'
|
||||
Return ' (sursa: ANAF)'
|
||||
Case toStare.cSursa == 'CACHE'
|
||||
Return ' (sursa: CACHE ' + Dtoc(Nvl(toStare.dDataSursa, Date())) + ')'
|
||||
Case toStare.cSursa == 'CACHE_INDISP'
|
||||
Return ' (sursa: CACHE ' + Dtoc(Nvl(toStare.dDataSursa, Date())) + ', ANAF indisponibil)'
|
||||
Endcase
|
||||
Return ''
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE TextPerioadaTVA
|
||||
@@ -744,6 +919,11 @@ DEFINE CLASS anaf_verif_cautare AS Custom
|
||||
If !Empty(toStare.cMesajScpTVA)
|
||||
lcTxt = m.lcTxt + 'Mesaj ANAF: ' + Alltrim(toStare.cMesajScpTVA) + Chr(13)
|
||||
Endif
|
||||
If toStare.lTvaIncasareANAF
|
||||
lcTxt = m.lcTxt + 'TVA la incasare' + ;
|
||||
Iif(!Empty(toStare.dInceputTvaInc), ' din ' + Dtoc(toStare.dInceputTvaInc), '') + ;
|
||||
Iif(!Empty(toStare.dSfarsitTvaInc), ' pana la ' + Dtoc(toStare.dSfarsitTvaInc), '') + Chr(13)
|
||||
Endif
|
||||
If !Empty(m.lcTxt)
|
||||
lcTxt = m.lcTxt + Chr(13)
|
||||
Endif
|
||||
@@ -849,7 +1029,9 @@ DEFINE CLASS anaf_verif_cautare AS Custom
|
||||
poANAFInlocuire = .Null.
|
||||
|
||||
lcCursor = This.oForm.crs_cursor
|
||||
lcDenAles = Alltrim(Nvl(Evaluate(m.lcCursor + '.denumire'), Nvl(Evaluate(m.lcCursor + '.nume'), '')))
|
||||
*** cursorul de cautare are, dupa formular, fie denumire, fie nume
|
||||
lcDenAles = Iif(Type(m.lcCursor + '.denumire') = 'C', Alltrim(Nvl(Evaluate(m.lcCursor + '.denumire'), '')), ;
|
||||
Iif(Type(m.lcCursor + '.nume') = 'C', Alltrim(Nvl(Evaluate(m.lcCursor + '.nume'), '')), ''))
|
||||
lcCodAles = Alltrim(Nvl(Evaluate(m.lcCursor + '.cod_fiscal'), ''))
|
||||
|
||||
If Isnull(This.oStare)
|
||||
@@ -969,7 +1151,9 @@ DEFINE CLASS anaf_verif_cautare AS Custom
|
||||
Endif
|
||||
|
||||
lcCursor = This.oForm.crs_cursor
|
||||
lcDenAles = Alltrim(Nvl(Evaluate(m.lcCursor + '.denumire'), Nvl(Evaluate(m.lcCursor + '.nume'), '')))
|
||||
*** cursorul de cautare are, dupa formular, fie denumire, fie nume
|
||||
lcDenAles = Iif(Type(m.lcCursor + '.denumire') = 'C', Alltrim(Nvl(Evaluate(m.lcCursor + '.denumire'), '')), ;
|
||||
Iif(Type(m.lcCursor + '.nume') = 'C', Alltrim(Nvl(Evaluate(m.lcCursor + '.nume'), '')), ''))
|
||||
lcCodAles = Alltrim(Nvl(Evaluate(m.lcCursor + '.cod_fiscal'), ''))
|
||||
lcCodOk = Iif(This.oStare.lPlatitorANAF, 'RO', '') + This.cCui
|
||||
|
||||
@@ -1292,7 +1476,7 @@ Endfunc && caut_parteneri_xml
|
||||
* author : paula.mutu
|
||||
* -- SIR CU ID-URI TIP PARTENER PENTRU -1,-2 (CLIENT/FURNIZOR)
|
||||
******************************************* INCEPUT:caut_partener *******************************************
|
||||
Procedure caut_partener(tcIdTipPart, tcTitlu, tlToateIreg, tlNou)
|
||||
Procedure caut_partener(tcIdTipPart, tcTitlu, tlToateIreg, tlNou, tlVerificaANAF, tdDataDoc)
|
||||
|
||||
Private pnIdTip, pcSir_Id_tip_part
|
||||
Store '' To pcSir_Id_tip_part
|
||||
@@ -1309,7 +1493,7 @@ Procedure caut_partener(tcIdTipPart, tcTitlu, tlToateIreg, tlNou)
|
||||
Local lcTitlu, lcFiltru, lcSchema, lcOrder, lcNumeProc, lcTitluColoane
|
||||
Store "" To loCauta
|
||||
|
||||
lcSelect = [select denumire, cod_fiscal, id_part from vnom_parteneri ]
|
||||
lcSelect = [select denumire, cod_fiscal, id_part, tip_persoana from vnom_parteneri ]
|
||||
lcFiltru = [1=2]
|
||||
lcSchema = []
|
||||
lcOrder = [denumire]
|
||||
@@ -1331,8 +1515,26 @@ Procedure caut_partener(tcIdTipPart, tcTitlu, tlToateIreg, tlNou)
|
||||
lcNumeProc = []
|
||||
Endif
|
||||
lcTitluColoane = [Denumire,Cod fiscal,Id]
|
||||
|
||||
Local lnNivelANAF
|
||||
Private poVerifAlegere, poANAFInlocuire
|
||||
poVerifAlegere = .Null.
|
||||
poANAFInlocuire = .Null.
|
||||
If m.tlVerificaANAF
|
||||
lnNivelANAF = ANAF_NivelVerificare()
|
||||
If m.lnNivelANAF > 0
|
||||
poVerifAlegere = Createobject('anaf_verif_cautare')
|
||||
poVerifAlegere.dDataDoc = ANAF_CaData(m.tdDataDoc)
|
||||
poVerifAlegere.nNivel = m.lnNivelANAF
|
||||
Endif
|
||||
Endif
|
||||
|
||||
loCauta = cauta_alfa(lcSelect, lcFiltru, lcSchema, lcOrder, lccoloane, lcTitlu, lcTitluColoane, lcNumeProc, tlToateIreg, lcFiltruOriginal) && 11.07.2007
|
||||
|
||||
If Type('gnbuton') = 'N' And gnbuton = 1
|
||||
AplicaInlocuirePartenerANAF(loCauta, poANAFInlocuire)
|
||||
Endif
|
||||
|
||||
Return loCauta
|
||||
|
||||
Endproc
|
||||
@@ -2970,7 +3172,7 @@ Endproc && caut_politici_curente_util
|
||||
************************************** SFARSIT: caut_politici_curente_util **************************************
|
||||
***************************************** INCEPUT:caut_explicatie_tva *******************************************
|
||||
Function caut_explicatie_tva
|
||||
Parameters tnIdJtva, tnPornire, tlDesktop, tlTipEx
|
||||
Parameters tnIdJtva, tnPornire, tlDesktop, tlTipEx, tnCotaTva
|
||||
*!* tlTipEx = 0 - toate
|
||||
*!* = 1 - doar TVA exigibil din JC
|
||||
*!* = 2 - doar TVA neexigibil din JC
|
||||
@@ -3016,6 +3218,10 @@ Function caut_explicatie_tva
|
||||
lcFiltruOriginal = [id_jtva_coloana in (select id_tva from vjtva_coloane where ] + ;
|
||||
[id_jtva_ex is not null)]
|
||||
Endcase
|
||||
*** filtru suplimentar pe cota TVA a liniei curente; fara procent (0/gol) se pastreaza lista completa
|
||||
If Vartype(tnCotaTva) = 'N' And tnCotaTva > 0
|
||||
lcFiltruOriginal = lcFiltruOriginal + [ and cota_tva = ] + Alltrim(Str(tnCotaTva, 10, 2))
|
||||
Endif
|
||||
*!* *!* If tnIdJtva > 0
|
||||
*!* *!* lcFiltruOriginal = [jc * 4 + jv * 2 + decode(afisat,0,0,1) in ] + ;
|
||||
*!* *!* [(select jc * 4 + jv * 2 + decode(afisat,0,0,1) from ] + gcS + [.vjtva_coloane ] + ;
|
||||
@@ -3824,7 +4030,7 @@ ENDFUNC
|
||||
|
||||
***********************************************************************************************************
|
||||
Function caut_client_contract_activ
|
||||
Lparameters tcCond, tnIdPart, tnIdCtr
|
||||
Lparameters tcCond, tnIdPart, tnIdCtr, tlVerificaANAF, tdDataDoc
|
||||
*** tnIdCtr: daca dau id_ctr direct (facturile de penalitati) selectez numai acest contractul indiferent de iscontract_valid()
|
||||
|
||||
Local lcSelect, lcFiltruInitial, lcFiltru, lcSchema, lcOrder, lcColoane, lcTitlu, lcTitluColoane, lcNumeProc, lcPrimaColoana
|
||||
@@ -3880,8 +4086,25 @@ select c.id_ctr, c.id_part, p.denumire, p.cod_fiscal, c.data, c.numar, c.data_in
|
||||
lcNumeProc = []
|
||||
lcPrimaColoana = [denumire,numar]
|
||||
|
||||
Local lnNivelANAF
|
||||
Private poVerifAlegere, poANAFInlocuire
|
||||
poVerifAlegere = .Null.
|
||||
poANAFInlocuire = .Null.
|
||||
If m.tlVerificaANAF
|
||||
lnNivelANAF = ANAF_NivelVerificare()
|
||||
If m.lnNivelANAF > 0
|
||||
poVerifAlegere = Createobject('anaf_verif_cautare')
|
||||
poVerifAlegere.dDataDoc = ANAF_CaData(m.tdDataDoc)
|
||||
poVerifAlegere.nNivel = m.lnNivelANAF
|
||||
Endif
|
||||
Endif
|
||||
|
||||
loCauta = cauta_alfa(lcSelect, lcFiltru, lcSchema, lcOrder, lcColoane, lcTitlu, lcTitluColoane, lcNumeProc, , lcFiltruInitial, lcPrimaColoana)
|
||||
|
||||
If Type('gnbuton') = 'N' And gnbuton = 1
|
||||
AplicaInlocuirePartenerANAF(loCauta, poANAFInlocuire, pcSir_Id_tip_part)
|
||||
Endif
|
||||
|
||||
Return loCauta
|
||||
ENDFUNC
|
||||
***********************************************************************************************************
|
||||
|
||||
@@ -261,6 +261,7 @@ Define Class oDateFactura As Custom
|
||||
If INLIST(m.tnTip, 2, 6, 52) And Type('goContract') <> 'U' && FACTURARE DIN ROACONTRACTE
|
||||
.id_client = goContract.id_part
|
||||
.nume_client = goContract.denumire
|
||||
.cod_fiscal = ALLTRIM(NVL(goContract.cod_fiscal, ''))
|
||||
.listaid = goContract.id_ctr
|
||||
.descriere = goContract.contract
|
||||
.id_sectie = goContract.id_sectie
|
||||
|
||||
1165
programe/ofacturare_editare.prg
Normal file
1165
programe/ofacturare_editare.prg
Normal file
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,10 @@
|
||||
*!* 03.05.2022
|
||||
*!* oscrie_vanzare_din_stoc - completeaza pack_facturare.adauga_articol_factura_stoc(taxcode)
|
||||
|
||||
*!* 18.08.2026
|
||||
*!* marius.mutu
|
||||
*!* oscrie_vanzare_din_stoc - pretul de achizitie si pretul in valuta se trimit cu cel putin 4 zecimale, cate pastreaza stocul
|
||||
|
||||
**************************************** INCEPUT: initializeaza_vanzare_din_stoc ******************************
|
||||
Procedure initializeaza_vanzare_din_stoc
|
||||
Lparameters tnIdSet, toActAnterior
|
||||
@@ -357,8 +361,8 @@ Else
|
||||
lcSql = [begin ] + gcS + [.pack_facturare.adauga_articol_factura_stoc(] + ;
|
||||
Alltrim(Str(poArticol.id_articol)) + [,] + ;
|
||||
['] + Strtran(Alltrim(Nvl(poArticol.serie,[])),['],['']) + [',] + ;
|
||||
Alltrim(Str(poArticol.pret_achizitie,18,gnPPret)) + [,] + ;
|
||||
Alltrim(Str(poArticol.pretd,18,gnPPretVal)) + [,] + ;
|
||||
Alltrim(Str(poArticol.pret_achizitie,18,Max(gnPPret,4))) + [,] + ;
|
||||
Alltrim(Str(poArticol.pretd,18,Max(gnPPretVal,4))) + [,] + ;
|
||||
Alltrim(Str(poArticol.id_valuta_d)) + [,] + ;
|
||||
Alltrim(Str(poArticol.Pret,18,Iif(poDate.in_valuta = 1,gnPVal,gnPPretV))) + [,] + ;
|
||||
Iif(poDate.in_valuta=1,Alltrim(Str(poArticol.id_valuta)),[NULL]) + [,] + ;
|
||||
|
||||
@@ -80,6 +80,13 @@
|
||||
*!* In xsets s-a modificat 21% de la 01.08.2025
|
||||
|
||||
|
||||
*!* 28.07.2026
|
||||
*!* marius.mutu
|
||||
*!* achizitie_import - blocul de TVA din DVI poate avea valuta si curs proprii, diferite de ale
|
||||
*!* facturii (inclusiv fara valuta), iar factura poate avea discount financiar; cursorul introdc
|
||||
*!* primeste coloanele rand_dvi si valuta_proprie.
|
||||
|
||||
|
||||
#Define CRLF Chr(13) + Chr(10)
|
||||
|
||||
********* INCEPUT: lans_Nir_Bon ***********
|
||||
@@ -1557,8 +1564,8 @@ Procedure achizitie_import
|
||||
poAct.id_valuta As id_valuta, poAct.Curs As Curs, poAct.nume_val As nume_val, poAct.dataact as dataact, poAct.fdoc as fdoc, poAct.id_fdoc as id_fdoc, 0 as se_scrie, poAct.tva_incasare as tva_incasare, ;
|
||||
16777215 As doc_color, Space(10) As doc_label, ;
|
||||
'B' As tip_rand, Space(80) As doc_key, 00000000 As nr_doc, ;
|
||||
00000000000000.0000 As suma_doc, 00000000000000.0000 As suma_doc_val, 0 As mod_manual, ;
|
||||
Space(20) As scd_orig, Space(20) As ascd_orig ;
|
||||
00000000000000.0000 As suma_doc, 00000000000000.0000 As suma_doc_val, 0 As mod_manual, 0 As expl_manual, ;
|
||||
Space(20) As scd_orig, Space(20) As ascd_orig, 0 As rand_dvi, 0 As valuta_proprie ;
|
||||
FROM cnote_contabile N ;
|
||||
WHERE N.id_set = poAct.id_set ;
|
||||
INTO Cursor introdc Readwrite Order By ordine
|
||||
@@ -1615,7 +1622,7 @@ Procedure achizitie_import
|
||||
*!* 16.07.2026 claude - F1: index unic de sortare pe introdc, o singura data, inainte de Show
|
||||
*!* (niciodata re-INDEX ulterior sub grid - vezi docs/propuneri_import_unificat.md)
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='T','3', tip_rand='D','4', '5') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
SELECT introdc
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
* ointroduceri_efactura.prg
|
||||
|
||||
Procedure importEfacturaPrimite
|
||||
DO vizImportEFactura WITH 'PRIMITE'
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE importEfacturaTrimise
|
||||
DO vizImportEFactura WITH 'TRIMISE'
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE vizImportEFactura
|
||||
LPARAMETERS tcTip
|
||||
* tcTIP: PRIMITE/TRIMISE
|
||||
|
||||
Private poFacturi, poFacturiDetalii
|
||||
Local loFrmFacturi As "frm_efactura_import", lcTip, llPrimite
|
||||
Local lcData1, lcFiltru, lcFiltruOriginal, lcOrder, lcSchema, lcgroup, llAfiseaza, llModParam
|
||||
poFacturi = Null
|
||||
poFacturiDetalii = Null
|
||||
|
||||
lcTip = IIF(TYPE('tcTip') = 'C' and !EMPTY(m.tcTip), UPPER(ALLTRIM(m.tcTip)), 'PRIMITE')
|
||||
llPrimite = (m.lcTip = 'PRIMITE')
|
||||
|
||||
lcTabel = IIF(m.lcTip = 'PRIMITE', 'anaf_vefactura_primit', 'anaf_vefactura_trimis')
|
||||
|
||||
* FACTURI PRIMITE/TRIMISE
|
||||
lcData1 = '01' + Padl(Int(m.gnLuna),2,'0') + Alltrim(Str(m.gnAn))
|
||||
TEXT To lcSchema Noshow
|
||||
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), partener C(200), id_incarcare C(36), id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal C(30) null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4), descriere M null, detalii_plata M null, diferenta N(16,4), procesat N(1)
|
||||
ENDTEXT
|
||||
|
||||
TEXT To lcSelect TEXTMERGE Noshow
|
||||
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, partener, id_incarcare, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, cod_fiscal, cod_fiscal_emitent, cod_fiscal_beneficiar, detalii, total_fara_tva, total_tva, total_cu_tva, discount_fara_tva, taxe_fara_tva, valoare_fara_tva, total_de_plata, nume_valuta, test, jtotctva, descriere, detalii_plata, NVL(total_cu_tva, 0.00)-NVL(jtotctva, 0.00) as diferenta, procesat FROM <<m.lcTabel>>
|
||||
ENDTEXT
|
||||
lcOrder = [data_act,numar_act,data_raspuns]
|
||||
lcgroup = []
|
||||
lcFiltru = [(extract(year from data_act) = ?gnAn and extract(month from data_act) = ?gnLuna) or (data_act is null and data_raspuns >= to_date('] + m.lcData1 + [','ddmmyyyy'))]
|
||||
lcFiltruOriginal = []
|
||||
llModParam = .T.
|
||||
llAfiseaza = .F.
|
||||
|
||||
gencursor('poFacturi', 'crsFacturi', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
|
||||
poFacturi.ca_baza1.afisare()
|
||||
Select crsFacturi
|
||||
Go Top
|
||||
|
||||
* DETALII FACTURI PRIMITE/TRIMISE/EMISE
|
||||
TEXT To lcSchema Noshow
|
||||
id_tip N(10) null, cont c(4) null, id_articol N(20) null, id_gestiune N(20) null, id N(20), id_efactura N(20), nr N(5), articol V(250), descriere V(250), detalii M, cantitate N(18,6), um V(20), um_iso V(50), id_um I, um_roa V(50), pret N(20,6), proctva N(7,2), valoarefaratva N(20,6), in_stoc N(1), articol_roa V(250)
|
||||
ENDTEXT
|
||||
TEXT To lcSelect Noshow
|
||||
select CAST(0 as number(10)) as id_tip, CAST('' as Varchar2(4)) as cont, CAST(null as Number(20)) as id_articol, CAST(null as Number(20)) as id_gestiune, id, id_efactura, nr, articol, descriere, detalii, cantitate, um, um_iso, id_um, um_roa, pret, proctva, valoarefaratva, 0 as in_stoc, CAST('' as Varchar2(250)) as articol_roa from anaf_vefactura_detalii
|
||||
ENDTEXT
|
||||
lcOrder = [nr]
|
||||
lcgroup = []
|
||||
lcFiltru = [1=2] && IIF(!EMPTY(NVL(crsFacturiPrimite.id,0)), [id_efactura=] + ALLTRIM(STR(crsFacturiPrimite.id)), [1=2])
|
||||
lcFiltruOriginal = []
|
||||
llModParam = .T.
|
||||
llAfiseaza = .F.
|
||||
|
||||
gencursor('poFacturiDetalii', 'crsDetaliiFacturi', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
|
||||
poFacturiDetalii.ca_baza1.afisare()
|
||||
|
||||
* Cursoare helper
|
||||
CREATE CURSOR cTip (id I, in_stoc N(1), tip V(50), cont V(4))
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Nedefinit','', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. mat. nestoc.','604', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. Energie','6051', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. Apa','6052', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. Gaze','6053', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. chirii','6123', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. colaboratori','621', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. comisioane','622', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. protocol','623', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. transp. bunuri/pers.','624', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. deplasari','625', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. posta/telecom.','626', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ch. terti','628', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Altele','461', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('-----------------','', 0)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Marfuri','371', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Materii prime','301', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Materiale auxiliare','3021', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ambalaje','381', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Obiecte de inventar','303', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Amenajari provizorii','323', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Mat. spre prelucrare','8032', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Mat. in pastrare/consig.','8033', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Discount financiar','767', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Combustibili','3022', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Piese de schimb','3024', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Alte mat. consumabile','3028', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Discount comercial','609', 1)
|
||||
INSERT INTO cTip (tip, cont, in_stoc) VALUES ('Ambalaje SGR','461', 0)
|
||||
|
||||
REPLACE ALL id WITH RECNO()-1 IN cTip
|
||||
GO TOP IN cTip
|
||||
INDEX on id TAG id
|
||||
|
||||
*!* llSucces = goExecutor.oExecuta("select id_articol, denumire, codmat from vnom_articole where inactiv = 0", 'cArticole')
|
||||
|
||||
*!* SELECT cArticole
|
||||
*!* INDEX on id_articol TAG id_articol
|
||||
|
||||
llSucces = goExecutor.oExecuta([select distinct nume_gestiune,cgest,id_gestiune,nr_pag,cont from vgest_gestiuni_util where inactiv = 0 and id_util = ] + Alltrim(Str(m.gnIdUtil)), 'cGestiuni')
|
||||
SELECT cGestiuni
|
||||
INDEX on id_gestiune TAG id_gest
|
||||
|
||||
llSucces = goExecutor.oExecuta("select cod_um_iso, um_iso from syn_vnom_um_iso", 'cUMISO')
|
||||
SELECT cUMISO
|
||||
INDEX on cod_um_iso TAG cod_um_iso
|
||||
|
||||
llSucces = goExecutor.oExecuta("select id, um, cod_um_iso, um_iso from vnom_um", 'cUM')
|
||||
SELECT cUM
|
||||
INDEX on id TAG id
|
||||
|
||||
Select crsFacturi
|
||||
loFrmFacturi = Createobject("frm_import_efactura", m.llPrimite)
|
||||
* Do Form anaf_efactura Name loFrmBorderou Linked With this Noshow
|
||||
|
||||
loFrmFacturi.Show(1)
|
||||
|
||||
Use In (Select('crsFacturi'))
|
||||
Use In (Select('crsDetaliiFacturi'))
|
||||
Use In (Select('cTip'))
|
||||
Use In (Select('cArticole'))
|
||||
Use In (Select('cGestiuni'))
|
||||
Endproc && vizFacturiPrimite
|
||||
|
||||
@@ -397,7 +397,7 @@ Function verific_partener
|
||||
|
||||
ll_l=.F.
|
||||
|
||||
If Empty(tcCont) Or Type('tccont')#'C'
|
||||
If Type('tccont')#'C' Or Empty(Nvl(tcCont,''))
|
||||
Return ll_l
|
||||
Else
|
||||
lcCont = Alltrim(tcCont)
|
||||
@@ -439,7 +439,7 @@ Function verific_partener
|
||||
llNou = .T.
|
||||
*!* modificare 10.12.2010
|
||||
loCauta = CautPartenerContabilitate(GetHash([cTitlu=>] + Alltrim(lcTitlu)+[??cCont=>] + Alltrim(lcCont) + [??] + ;
|
||||
[lAdaugCorespondente=>1]))
|
||||
[lAdaugCorespondente=>1??lVerificaANAF=>1]))
|
||||
*!* locauta = caut_parteneri(lcCont, lcTitlu,,llNou)
|
||||
*!* modificare 10.12.2010 ^
|
||||
If !Empty(loCauta.id_part)
|
||||
@@ -889,7 +889,7 @@ Procedure verificare_note_contabile
|
||||
*!* modificare 10.12.2010
|
||||
loPart = CautPartenerContabilitate(GetHash([cTitlu=>] + Alltrim(lcTitlu) + [??] + ;
|
||||
[cCont=>] + Alltrim(lcCont) + [??] + ;
|
||||
[lAdaugCorespondente=>1]))
|
||||
[lAdaugCorespondente=>1??lVerificaANAF=>1]))
|
||||
*!* loPart = caut_parteneri(lcCont , lcTitlu)
|
||||
*!* modificare 10.12.2010 ^
|
||||
Select (lcAct)
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
*!* 22.07.2025
|
||||
*!* GetNamePermutations - limitare la 4 cuvinte si maxim 10 permutari
|
||||
|
||||
*!* 31.07.2026
|
||||
*!* marius.mutu
|
||||
*!* verifica_partener_show_info: marcaj de provenienta (cache ANAF) langa denumirea firmei, cand disponibil
|
||||
|
||||
#Include COMUN\ROA.H
|
||||
|
||||
Define Class oexecutor As Custom
|
||||
@@ -4597,6 +4601,7 @@ Procedure verificare_parteneri
|
||||
|
||||
Endproc && verificare_parteneri
|
||||
|
||||
*!* 01.08.2026 marius.mutu istoricul e comun tuturor firmelor, nu se mai filtreaza pe schema_sursa
|
||||
Procedure verificare_parteneri_istoric
|
||||
Lparameters tcCodFiscal, tcNume
|
||||
|
||||
@@ -4613,7 +4618,9 @@ Procedure verificare_parteneri_istoric
|
||||
Endif
|
||||
|
||||
Text To lcSql Noshow
|
||||
select id, dataora, id_util, dataorav, id_utilv, cod_fiscal, firma, adresa, judet, regcom, codpostal, telefon, fax, datatvamfin, platitortvamfin, stare, platitortvavies, util, utilv
|
||||
select id, dataora, id_util, dataorav, id_utilv, cod_fiscal, firma, adresa, judet, regcom, codpostal, telefon, fax, datatvamfin, platitortvamfin, stare, platitortvavies,
|
||||
dataorav_anaf, tvaincasare, splittva, inactiv, data_inceput_scptva, data_sfarsit_scptva, data_anul_imp_scptva, data_inceput_tvainc, data_sfarsit_tvainc, data_inactivare, data_reactivare,
|
||||
util, utilv
|
||||
from vistoric_coduri_fiscale
|
||||
where cod_fiscal = ?pcCodFiscal
|
||||
Endtext
|
||||
@@ -4764,7 +4771,7 @@ Function verifica_partener_show_info
|
||||
*** tcMesajIntrebare: IN, optional, daca se intreaba ceva la sfarsitul formularului (ex: Se completeaza datele in formularul partener nou?)
|
||||
|
||||
Local lcCodFiscal, lcDenumire, lcText, llCodRO, llPlatitorTVAMfin, llPlatitorTVAVIES, lnDialogType
|
||||
Local lnRaspuns, loPartener
|
||||
Local lnRaspuns, loPartener, lcProvenienta
|
||||
|
||||
lcCodFiscal = Transform(m.tcCodFiscal)
|
||||
lcDenumire = Transform(m.tcDenumire)
|
||||
@@ -4776,9 +4783,16 @@ Function verifica_partener_show_info
|
||||
llTvaIncasare = loPartener.tvaincasare
|
||||
llSplitTVA = loPartener.splittva
|
||||
llInactiv = loPartener.inactiv
|
||||
*!* 01.08.2026 marius.mutu: marcaj explicit al sursei (ANAF live / cache), nu doar pe randurile din cache
|
||||
lcProvenienta = ''
|
||||
If Pemstatus(m.loPartener, 'sursa', 5) And !Empty(Alltrim(Nvl(loPartener.sursa, '')))
|
||||
lcProvenienta = Iif(Alltrim(Nvl(loPartener.sursa, '')) == 'ANAF', '(sursa: ANAF)', ;
|
||||
'(sursa: CACHE ' + Dtoc(Nvl(loPartener.data_sursa, Date())) + Iif(Alltrim(Nvl(loPartener.sursa, '')) == 'CACHE_INDISP', ', ANAF indisponibil', '') + ')')
|
||||
Endif
|
||||
|
||||
lcText = 'VERIFICARE CIF: ' + m.lcCodFiscal + ' ' + m.lcDenumire + crlf + crlf + ;
|
||||
Alltrim(loPartener.firma) + crlf + ;
|
||||
Iif(!Empty(m.lcProvenienta), m.lcProvenienta + crlf, '') + ;
|
||||
Iif((m.llPlatitorTVAMfin And !m.llCodRO) Or (!m.llPlatitorTVAMfin And m.llCodRO), ' *** ATENTIE *** ', '') + ;
|
||||
Iif(m.llPlatitorTVAMfin, "PLATITOR TVA (" + Alltrim(loPartener.datatvamfin) + ")", "NEPLATITOR TVA") + crlf + ;
|
||||
'Stare: ' + Alltrim(loPartener.stare) + crlf + ;
|
||||
|
||||
@@ -73,6 +73,42 @@
|
||||
*!* anulare din oficiu) si mesajul ANAF integral (mesaj_ScpTVA), citite din cursorul deja parsat de
|
||||
*!* ParseJsonANAFv8; parsarea esuata a datelor de perioada se logheaza
|
||||
|
||||
*!* 31.07.2026
|
||||
*!* marius.mutu
|
||||
*!* VerificareANAF: cache ANAF pe ISTORIC_CODURI_FISCALE (SalveazaIstoricDinCursor/CitesteIstoricPentruCoduri/
|
||||
*!* OrdineCache/ZileCache/NormalizeazaCoduriCursor); VerificaListaCIF si ANAF_VerificaCuiSingle salveaza
|
||||
*!* rezultatele ANAF in istoric; VerificaListaCIF primeste al patrulea parametru optional tcTraseu
|
||||
*!* ('UNIC'/'MASA', implicit MASA) si citeste ordinea cu OrdineCache(tcTraseu), cu plasa de siguranta la
|
||||
*!* tacere din istoric si provenienta (sursa/data_sursa) marcata in crsANAF si logata; VERIFICARE_CIF
|
||||
*!* trimite si tvaincasare/splittva/inactiv la salvare; sursa/data_sursa ajung si pana la obiectul
|
||||
*!* intors de VERIFICARE_CIF (GetEmptyMfinObj, Procedure ANAF, cursorul cVerificareCod)
|
||||
|
||||
*!* 01.08.2026
|
||||
*!* marius.mutu
|
||||
*!* VerificaListaCIF, ramura CACHE,ANAF: apelul ramas catre ANAF_SincronWebService_PlatitorTva foloseste
|
||||
*!* acum un alias temporar (mergeuit apoi in crsANAF), ca randurile deja citite din cache sa nu mai fie
|
||||
*!* sterse si reetichetate gresit CACHE_INDISP; plus golire explicita a aliasului la intrarea in
|
||||
*!* VerificaListaCIF, ca sa nu mai acumuleze intre apeluri succesive cu alias implicit (Procedure ANAF) -
|
||||
*!* defecte gasite la revizia de ansamblu dupa transa cache ANAF
|
||||
|
||||
*!* 01.08.2026
|
||||
*!* marius.mutu
|
||||
*!* SalveazaIstoricDinCursor trimite acum provenienta randului (sursa) la save_istoric_cod_fiscal, al
|
||||
*!* 27-lea parametru pnDinCache; pachetul Oracle nu mai improspateaza DATAORAV_ANAF cand randul vine
|
||||
*!* din cache (CACHE/CACHE_INDISP) - doar cand vin efectiv date noi de la ANAF - dar DATAORAV/ID_UTILV
|
||||
*!* (urma de audit "cine si cand a verificat partenerul") se actualizeaza in continuare, indiferent de
|
||||
*!* provenienta; altfel cache-ul isi reseta singur ceasul de prospetime la fiecare citire si nu mai
|
||||
*!* expira niciodata
|
||||
|
||||
*!* 02.08.2026
|
||||
*!* marius.mutu
|
||||
*!* SalveazaIstoricDinCursor sare peste randurile provenite din cache - au fost deja salvate cand au
|
||||
*!* ajuns prima data din ANAF; VerificaListaCIF lasa o singura linie in goLog cu totalul randurilor
|
||||
*!* completate din cache (CACHE si CACHE_INDISP), in loc de o linie per rand; CitesteIstoricPentruCoduri
|
||||
*!* interogheaza codurile pe transe de maxim 1000, legate cu OR in aceeasi interogare (peste 1000
|
||||
*!* elemente "in (...)" da ORA-01795); plasa de siguranta din VerificaListaCIF aduna codurile ramase
|
||||
*!* fara raspuns si cere istoricul intr-un singur apel, in loc de un apel Oracle per cod
|
||||
|
||||
*!* http://ec.europa.eu/taxation_customs/vies/viesquer.do
|
||||
*!* http://localhost/contafinupdate/verificarecod.aspx/verificarecod/verificare/CIF/1879855/MFIN
|
||||
*!* http://localhost/contafinupdate/verificarecod.aspx/verificarecod/verificare/CNP/1810228134187
|
||||
@@ -598,7 +634,7 @@ Define Class VerificareCod As Custom
|
||||
Local loEx As Exception
|
||||
Local lcMfinanteURL, lcMfinanteParams, lcRomfastURL, llMFINURL, loMFIN, loVIES, lcProcedura, llInterogareAnaf
|
||||
Local lStare, lcApart, lcBloc, lcDataTVAMFIN, lcEtaj, lcLocalitate, lcNr, lcScara, lcStrada
|
||||
Local llPlatitorTVAMFIN, lnSucces, llTVAIncasare, llSplitTVA, llInactiv, ldData
|
||||
Local llPlatitorTVAMFIN, lnSucces, llTVAIncasare, llSplitTVA, llInactiv, ldData, lcSqlIstoric, lcSursa, ldDataSursa
|
||||
|
||||
Local lcTipInterogare, llInterogareVies, llInterogareMfin
|
||||
If Empty(tcTipInterogare) Or Type('tcTipInterogare') <> 'C'
|
||||
@@ -653,11 +689,13 @@ Define Class VerificareCod As Custom
|
||||
llTVAIncasare = .F.
|
||||
llSplitTVA = .F.
|
||||
llInactiv = .F.
|
||||
lcSursa = ''
|
||||
ldDataSursa = {}
|
||||
|
||||
Create Cursor cVerificareCod (Valid L, eroare c(250), cod V(100) Null, firma V(100), adresa V(250), judet V(100), ;
|
||||
regcom V(30), codpostal V(20), telefon V(30), fax V(30), datatvamfin V(30), platitortvamfin L, VIES L, PlatitorTVA L, ;
|
||||
stare V(100), strada V(100), nr V(25), localitate V(100), Bloc V(30), Scara V(10), Etaj V(10), Apart V(20), ;
|
||||
tvaincasare L, splittva L, inactiv L)
|
||||
tvaincasare L, splittva L, inactiv L, sursa C(20), data_sursa D)
|
||||
|
||||
Cursortoxml("cVerificareCod", "lcXML", 1, 0, 0, "1")
|
||||
Select cVerificareCod
|
||||
@@ -698,6 +736,8 @@ Define Class VerificareCod As Custom
|
||||
llTvaIncasare = loMFIN.tvaIncasare
|
||||
llSplitTVA = loMFIN.SplitTVA
|
||||
llInactiv = loMFIN.Inactiv
|
||||
lcSursa = Nvl(loMFIN.sursa, 'ANAF')
|
||||
ldDataSursa = Nvl(loMFIN.data_sursa, {})
|
||||
Endif && llValid AND llInterogareMfin
|
||||
|
||||
If m.llValid And m.llRO And m.llInterogareMfin
|
||||
@@ -723,7 +763,9 @@ Define Class VerificareCod As Custom
|
||||
lcApart = loMFIN.apart
|
||||
llTvaIncasare = loMFIN.tvaIncasare
|
||||
llSplitTVA = loMFIN.SplitTVA
|
||||
llInactiv = loMFIN.Inactiv
|
||||
llInactiv = loMFIN.Inactiv
|
||||
lcSursa = Nvl(loMFIN.sursa, 'ANAF')
|
||||
ldDataSursa = Nvl(loMFIN.data_sursa, {})
|
||||
Endif && llValid AND llInterogareMfin
|
||||
|
||||
*!* VERIFICARE VIES pentru platitori TVA
|
||||
@@ -747,8 +789,8 @@ Define Class VerificareCod As Custom
|
||||
lcStrada = This.RemoveCharacters(m.lcStrada)
|
||||
|
||||
TRY
|
||||
Insert Into cVerificareCod(Valid, eroare, cod, firma, adresa, judet, regcom, codpostal, telefon, fax, datatvamfin, platitortvamfin, VIES, PlatitorTVA, stare, strada, nr, localitate, bloc, scara, etaj, apart, tvaincasare, splittva, inactiv) ;
|
||||
Values (m.llValid, Left(m.lcEroare, 250), m.lcVerificareCod, m.lcFirma, m.lcAdresa, m.lcJudet, m.lcRegCom, m.lcCodpostal, m.lcTelefon, m.lcFax, m.lcDataTVAMFIN, m.llPlatitorTVAMFIN, m.llVies, m.llPlatitorTVA, m.lcStare, m.lcStrada, m.lcNr, m.lcLocalitate, m.lcBloc, m.lcscara, m.lcetaj, m.lcapart, m.llTVAIncasare, m.llSplitTVA, m.llInactiv)
|
||||
Insert Into cVerificareCod(Valid, eroare, cod, firma, adresa, judet, regcom, codpostal, telefon, fax, datatvamfin, platitortvamfin, VIES, PlatitorTVA, stare, strada, nr, localitate, bloc, scara, etaj, apart, tvaincasare, splittva, inactiv, sursa, data_sursa) ;
|
||||
Values (m.llValid, Left(m.lcEroare, 250), m.lcVerificareCod, m.lcFirma, m.lcAdresa, m.lcJudet, m.lcRegCom, m.lcCodpostal, m.lcTelefon, m.lcFax, m.lcDataTVAMFIN, m.llPlatitorTVAMFIN, m.llVies, m.llPlatitorTVA, m.lcStare, m.lcStrada, m.lcNr, m.lcLocalitate, m.lcBloc, m.lcscara, m.lcetaj, m.lcapart, m.llTVAIncasare, m.llSplitTVA, m.llInactiv, m.lcSursa, m.ldDataSursa)
|
||||
|
||||
Select cVerificareCod
|
||||
Go Top
|
||||
@@ -757,7 +799,8 @@ Define Class VerificareCod As Custom
|
||||
|
||||
*** ROA salvez datele in istoric_coduri_fiscale
|
||||
If Type('goExecutor') = 'O'
|
||||
Private pcCodFiscal, pcFirma, pcAdresa, pcJudet, pcRegCom, pcCodPostal, pcTelefon, pcFax, pcDataTvamfin, pnPlatitorTvaMfin, pcStare, pnPlatitorTvaVies, pnInterogareVies
|
||||
Private pcCodFiscal, pcFirma, pcAdresa, pcJudet, pcRegCom, pcCodPostal, pcTelefon, pcFax, pcDataTvamfin, pnPlatitorTvaMfin, pcStare, pnPlatitorTvaVies, pnInterogareVies, ;
|
||||
pnInactiv, pnTvaIncasare, pnSplitTva
|
||||
pcCodFiscal = m.lcVerificareCod
|
||||
pcFirma = m.lcFirma && Strtran(Strtran(Upper(Alltrim(Nvl(m.lcFirma, ''))), Chr(170), 'S'), Chr(222), 'T')
|
||||
pcAdresa = m.lcAdresa && Strtran(Strtran(Upper(Alltrim(Nvl(m.lcAdresa, ''))), Chr(170), 'S'), Chr(222), 'T')
|
||||
@@ -771,8 +814,15 @@ Define Class VerificareCod As Custom
|
||||
pcStare = Upper(Alltrim(Nvl(m.lcStare, '')))
|
||||
pnPlatitorTvaVies = Iif(m.llPlatitorTVA, 1, 0)
|
||||
pnInterogareVies = Iif(m.llVies, 1, 0)
|
||||
If !Empty(m.pcFirma)
|
||||
lnSucces = goExecutor.oExecuta("begin pack_parteneri.save_istoric_cod_fiscal(?pcCodFiscal,?pcFirma,?pcAdresa,?pcJudet,?pcRegCom,?pcCodPostal,?pcTelefon,?pcFax,?pcDataTvamfin,?pnPlatitorTvaMfin,?pcStare,?pnPlatitorTvaVies,?pnInterogareVies,?gnIdUtil); end;")
|
||||
pnInactiv = Iif(m.llInactiv, 1, 0)
|
||||
pnTvaIncasare = Iif(m.llTVAIncasare, 1, 0)
|
||||
pnSplitTva = Iif(m.llSplitTVA, 1, 0)
|
||||
*!* 02.08.2026 marius.mutu: pe traseul ANAF randul complet e salvat deja de SalveazaIstoricDinCursor - a doua salvare doar insera un rand nou
|
||||
If !Empty(m.pcFirma) And !m.llInterogareAnaf
|
||||
*!* 02.08.2026 marius.mutu: tnDinCache = 2 - salvare fara date de interval, nu marcheaza prospetime de cache
|
||||
lcSqlIstoric = "begin pack_parteneri.save_istoric_cod_fiscal(?pcCodFiscal,?pcFirma,?pcAdresa,?pcJudet,?pcRegCom,?pcCodPostal,?pcTelefon,?pcFax,?pcDataTvamfin,?pnPlatitorTvaMfin,?pcStare," + ;
|
||||
"?pnPlatitorTvaVies,?pnInterogareVies,?gnIdUtil,?pnInactiv,?pnTvaIncasare,?pnSplitTva,tnDinCache=>2); end;"
|
||||
lnSucces = goExecutor.oExecuta(m.lcSqlIstoric)
|
||||
Endif
|
||||
Endif
|
||||
*** CONTAFIN salvez datele in istoric_coduri_fiscale
|
||||
@@ -810,7 +860,8 @@ Define Class VerificareCod As Custom
|
||||
|
||||
&& verificare serviciu web ANAF
|
||||
loVerificareANAF = Createobject("VerificareANAF") && validare.prg
|
||||
lcCursorVerificareANAF = loVerificareANAF.VerificaListaCIF(m.lcCodFiscal, m.ldData)
|
||||
*!* 01.08.2026 marius.mutu: verificare unui singur CIF cerut manual - traseu UNIC (ANAF intai), nu implicitul MASA
|
||||
lcCursorVerificareANAF = loVerificareANAF.VerificaListaCIF(m.lcCodFiscal, m.ldData, , 'UNIC')
|
||||
If Used(m.lcCursorVerificareANAF)
|
||||
If Reccount(m.lcCursorVerificareANAF) >= 1
|
||||
Select (m.lcCursorVerificareANAF)
|
||||
@@ -836,6 +887,8 @@ Define Class VerificareCod As Custom
|
||||
loMFIN.TVAIncasare = tvaincasare
|
||||
loMFIN.SplitTVA = splittva
|
||||
loMFIN.Inactiv = inactiv
|
||||
loMFIN.sursa = Nvl(sursa, 'ANAF')
|
||||
loMFIN.data_sursa = Nvl(data_sursa, {})
|
||||
Endif
|
||||
Endif
|
||||
|
||||
@@ -1559,7 +1612,9 @@ Define Class VerificareCod As Custom
|
||||
AddProperty(loMFIN, "Apart", "")
|
||||
AddProperty(loMFIN, "TvaIncasare", .F.)
|
||||
AddProperty(loMFIN, "SplitTVA", .F.)
|
||||
AddProperty(loMFIN, "Inactiv", .F.)
|
||||
AddProperty(loMFIN, "Inactiv", .F.)
|
||||
AddProperty(loMFIN, "sursa", '')
|
||||
AddProperty(loMFIN, "data_sursa", {})
|
||||
Return loMFIN
|
||||
Endfunc && GetEmptyMfinObj
|
||||
Enddefine
|
||||
@@ -1637,6 +1692,7 @@ Function ANAF_VerificaCuiSingle
|
||||
If !Empty(m.lcJsonString) And Left(m.lcJsonString, 1) = '{'
|
||||
Use In (Select(m.lcAliasTemp))
|
||||
loVerificareANAF.ParseJsonANAFv8(nfjsonread(m.lcJsonString), m.lcAliasTemp)
|
||||
loVerificareANAF.SalveazaIstoricDinCursor(m.lcAliasTemp, gnIdUtil)
|
||||
loResult = ANAF_VerdictDinCursor(m.lcAliasTemp, m.lnCuiCautat, @tlNegasit, @tcClasaEsec)
|
||||
Else
|
||||
tcClasaEsec = 'RASPUNS_NEINTELES'
|
||||
@@ -1671,6 +1727,8 @@ Function ANAF_VerdictDinCursor
|
||||
|
||||
If Used(m.tcAlias)
|
||||
Select (m.tcAlias)
|
||||
*!* 01.08.2026 marius.mutu: pozitionare explicita - apelantul poate lasa cursorul pe EOF
|
||||
Go Top
|
||||
lnReccountTemp = Reccount()
|
||||
If m.lnReccountTemp = 1 And !Empty(denumire)
|
||||
loResult = Createobject("empty")
|
||||
@@ -1683,6 +1741,9 @@ Function ANAF_VerdictDinCursor
|
||||
Addproperty(loResult, "dSfarsitScpTVA", Nvl(data_sfarsit_ScpTVA, {}))
|
||||
Addproperty(loResult, "dAnulareScpTVA", Nvl(data_anul_imp_ScpTVA, {}))
|
||||
Addproperty(loResult, "cMesajScpTVA", Nvl(mesaj_ScpTVA, ""))
|
||||
Addproperty(loResult, "lTvaIncasare", Nvl(tvaincasare, .F.))
|
||||
Addproperty(loResult, "dInceputTvaInc", Nvl(dataInceputTvaInc, {}))
|
||||
Addproperty(loResult, "dSfarsitTvaInc", Nvl(dataSfarsitTvaInc, {}))
|
||||
Else
|
||||
If m.lnReccountTemp = 1 And Empty(denumire) And Nvl(cui, 0) = m.tnCuiCautat
|
||||
tlNegasit = .T.
|
||||
@@ -1761,8 +1822,9 @@ Endfunc && ANAF_SondaPorneste
|
||||
*** .T. daca sonda in curs si-a primit raspunsul (indiferent de rezultat) sau nu exista nicio sonda activa
|
||||
*************************************
|
||||
Function ANAF_SondaAuSositRaspunsul
|
||||
Local loEx As Exception, llSosit
|
||||
|
||||
Local loEx As Exception, llSosit, llEroare
|
||||
llEroare = .F.
|
||||
|
||||
If Vartype(goANAF_SondaHTTP) <> 'O'
|
||||
Return .T.
|
||||
Endif
|
||||
@@ -1771,8 +1833,11 @@ Function ANAF_SondaAuSositRaspunsul
|
||||
llSosit = goANAF_SondaHTTP.WaitForResponse(0)
|
||||
Catch To loEx
|
||||
glANAF_SondaReusita = .F.
|
||||
llEroare = .T.
|
||||
ENDTRY
|
||||
IF m.llEroare
|
||||
Return .T.
|
||||
Endtry
|
||||
ENDIF
|
||||
If m.llSosit
|
||||
glANAF_SondaReusita = .T.
|
||||
Endif
|
||||
@@ -1809,6 +1874,9 @@ Endfunc && ANAF_SondaOpreste
|
||||
*********************************************
|
||||
Define Class VerificareANAF As Custom
|
||||
|
||||
*!* 01.08.2026 marius.mutu: ultimul esec ANAF de pe traseul batch - se arata o singura data, la final, doar daca raman coduri neacoperite
|
||||
cMesajANAF = ''
|
||||
|
||||
Procedure Init
|
||||
If !'nfjsonread' $ Lower(Set("Procedure"))
|
||||
Set Procedure To nfjsonread.prg Additive
|
||||
@@ -1822,16 +1890,27 @@ Define Class VerificareANAF As Custom
|
||||
*** VerificaListaCIF("31103995,1879855", Date(), "crsANAF")
|
||||
*** Verifica codurile fiscale din lista, la data
|
||||
*** Intoarce un cursor crsANAF (cui N(13), Data d, denumire c(60), adresa c(244), tva L, data_sfarsit d, data_anul_imp d, mesaj c(100))
|
||||
*** Ordinea ANAF/cache vine din OrdineCache(tcTraseu) - tcTraseu optional ('UNIC'/'MASA'), implicit 'MASA'
|
||||
*** cand lipseste sau e gol; pe CACHE,ANAF codurile cu rand proaspat in istoric nu se mai trimit la ANAF;
|
||||
*** indiferent de ordine, codurile ramase fara raspuns (tacere) se completeaza din istoric drept plasa de
|
||||
*** siguranta - codul gasit explicit "notFound" de ANAF nu atinge cache-ul, pentru ca primeste deja un
|
||||
*** rand in crsANAF (denumire goala) si nu mai e considerat "tacere"
|
||||
*************************************
|
||||
Function VerificaListaCIF
|
||||
Lparameters tcListaCIF, tdData, tcAlias
|
||||
Lparameters tcListaCIF, tdData, tcAlias, tcTraseu
|
||||
* tcListaCIF: lista coduri fiscale sau numele unui cursor cu coduri fiscale
|
||||
* tcTraseu: optional, 'UNIC' sau 'MASA' (vezi OrdineCache); implicit 'MASA' cand lipseste - apelantii
|
||||
* existenti (fara al patrulea parametru) raman pe comportamentul de azi
|
||||
|
||||
Local llUsed, lcCursorListaCIF, lnRec, lnRecs, lcAlias
|
||||
*!* 31.07.2026 marius.mutu: al patrulea parametru tcTraseu forteaza OrdineCache(tcTraseu) in loc de 'MASA' fix
|
||||
Local lcOrdine, ldData, lcAliasNorm, lcListaCoduriN, lcCursorRamas, lnCuiCurent, lcCodFiscalCurent, ldDataCurenta, llGasitCache, lcCursorAnafTemp, loRandAnaf, lnFaraRaspuns, lnCache, lnCacheIndisp, lcListaCoduriRamase
|
||||
|
||||
lcCursorListaCIF = ""
|
||||
llUsed = .F.
|
||||
lcAlias = ""
|
||||
lnFaraRaspuns = 0
|
||||
This.cMesajANAF = ''
|
||||
|
||||
goLog.Log('tcListaCIF: ' + tcListaCIF, 'VerificaListaCIF')
|
||||
If Used(tcListaCIF)
|
||||
@@ -1840,7 +1919,8 @@ Define Class VerificareANAF As Custom
|
||||
llUsed = .T.
|
||||
Else
|
||||
* lista
|
||||
lcCursorListaCIF = "cListaCIFTemp"
|
||||
*!* 01.08.2026 marius.mutu: nume unic - "cListaCIFTemp" colida cu variabila locala din overificari.vc2:2734
|
||||
lcCursorListaCIF = "crsListaCIFIntern"
|
||||
lnRecs = Getwordcount(m.tcListaCIF, ',')
|
||||
Create Cursor (lcCursorListaCIF) (cod_fiscal c(30) Null, data D null)
|
||||
For lnRec = 1 To m.lnRecs
|
||||
@@ -1849,14 +1929,176 @@ Define Class VerificareANAF As Custom
|
||||
Endfor
|
||||
Endif
|
||||
|
||||
lcAlias = This.ANAF_SincronWebService_PlatitorTva(m.lcCursorListaCIF, m.tdData, m.tcAlias)
|
||||
ldData = Iif(!Empty(m.tdData) And Type('tdData') = "D", m.tdData, Date())
|
||||
lcAlias = Iif(!Empty(m.tcAlias) And Type('tcAlias') = "C", m.tcAlias, "crsANAF")
|
||||
*!* 01.08.2026 marius.mutu: golire explicita la intrare - dupa fixul de mai jos, nimic altceva nu mai garanteaza un alias curat pe niciun traseu
|
||||
Use In (Select(m.lcAlias))
|
||||
lcOrdine = This.OrdineCache(Iif(Empty(m.tcTraseu), 'MASA', Upper(Alltrim(m.tcTraseu))))
|
||||
lcAliasNorm = This.NormalizeazaCoduriCursor(m.lcCursorListaCIF, m.ldData)
|
||||
|
||||
If Left(m.lcOrdine, 5) == 'CACHE'
|
||||
* CACHE,ANAF: codurile cu rand proaspat in istoric nu se mai trimit la ANAF
|
||||
lcListaCoduriN = ''
|
||||
Select (m.lcAliasNorm)
|
||||
Scan For cui_n <> 0
|
||||
lcListaCoduriN = m.lcListaCoduriN + Iif(Empty(m.lcListaCoduriN), '', ',') + Alltrim(Str(cui_n))
|
||||
Select (m.lcAliasNorm)
|
||||
Endscan
|
||||
This.CitesteIstoricPentruCoduri(m.lcListaCoduriN, m.ldData, m.lcAlias, 'CACHE')
|
||||
|
||||
lcCursorRamas = 'crsListaRamasANAF'
|
||||
Use In (Select(m.lcCursorRamas))
|
||||
Create Cursor (m.lcCursorRamas) (cod_fiscal c(30) Null, data D null)
|
||||
Select (m.lcAliasNorm)
|
||||
*!* 02.08.2026 marius.mutu: la ANAF ajung doar codurile care sunt CUI RO valid - restul nu pot fi nici in cache, nici verificate
|
||||
Scan For cui_n <> 0
|
||||
lnCuiCurent = cui_n
|
||||
lcCodFiscalCurent = cod_fiscal
|
||||
ldDataCurenta = data
|
||||
llGasitCache = .F.
|
||||
If m.lnCuiCurent <> 0 And Used(m.lcAlias) And Reccount(m.lcAlias) > 0
|
||||
Select (m.lcAlias)
|
||||
Locate For cui = m.lnCuiCurent
|
||||
llGasitCache = Found()
|
||||
Endif
|
||||
If !m.llGasitCache
|
||||
Insert Into (m.lcCursorRamas) (cod_fiscal, data) Values (m.lcCodFiscalCurent, m.ldDataCurenta)
|
||||
Endif
|
||||
Select (m.lcAliasNorm)
|
||||
Endscan
|
||||
|
||||
If Reccount(m.lcCursorRamas) > 0
|
||||
*!* 01.08.2026 marius.mutu: alias temporar - ANAF_SincronWebService_PlatitorTva goleste neconditionat aliasul primit (:2025), iar aici e deja populat din cache
|
||||
lcCursorAnafTemp = 'crsAnafBatchTemp'
|
||||
Use In (Select(m.lcCursorAnafTemp))
|
||||
lcCursorAnafTemp = This.ANAF_SincronWebService_PlatitorTva(m.lcCursorRamas, m.tdData, m.lcCursorAnafTemp)
|
||||
If Used(m.lcCursorAnafTemp) And Reccount(m.lcCursorAnafTemp) > 0
|
||||
Select (m.lcCursorAnafTemp)
|
||||
Scan
|
||||
Scatter Name loRandAnaf Memo
|
||||
Insert Into (m.lcAlias) FROM NAME loRandAnaf
|
||||
Select (m.lcCursorAnafTemp)
|
||||
Endscan
|
||||
Endif
|
||||
Use In (Select(m.lcCursorAnafTemp))
|
||||
Endif
|
||||
Use In (Select(m.lcCursorRamas))
|
||||
Else
|
||||
* ANAF,CACHE: comportamentul de azi, ANAF intai pentru toate codurile
|
||||
lcAlias = This.ANAF_SincronWebService_PlatitorTva(m.lcCursorListaCIF, m.tdData, m.lcAlias)
|
||||
Endif
|
||||
|
||||
If !m.llUsed
|
||||
Use In (Select(lcCursorListaCIF))
|
||||
Endif
|
||||
|
||||
* plasa de siguranta la tacere, indiferent de ordine: codurile fara rand in crsANAF (nici din ANAF,
|
||||
* nici din cache) se completeaza acum din istoric, marcate CACHE_INDISP; un rand deja prezent
|
||||
* (raspuns ANAF gasit sau notFound, sau deja servit din cache mai sus) nu e atins
|
||||
lcListaCoduriRamase = ''
|
||||
Select (m.lcAliasNorm)
|
||||
Scan For cui_n <> 0
|
||||
lnCuiCurent = cui_n
|
||||
llGasitCache = .F.
|
||||
If Used(m.lcAlias) And Reccount(m.lcAlias) > 0
|
||||
Select (m.lcAlias)
|
||||
Locate For cui = m.lnCuiCurent
|
||||
llGasitCache = Found()
|
||||
Endif
|
||||
If !m.llGasitCache
|
||||
lcListaCoduriRamase = m.lcListaCoduriRamase + Iif(Empty(m.lcListaCoduriRamase), '', ',') + Transform(m.lnCuiCurent)
|
||||
Endif
|
||||
Select (m.lcAliasNorm)
|
||||
Endscan
|
||||
Use In (Select(m.lcAliasNorm))
|
||||
|
||||
If !Empty(m.lcListaCoduriRamase)
|
||||
This.CitesteIstoricPentruCoduri(m.lcListaCoduriRamase, m.ldData, m.lcAlias, 'CACHE_INDISP')
|
||||
lnRecs = Getwordcount(m.lcListaCoduriRamase, ',')
|
||||
For lnRec = 1 To m.lnRecs
|
||||
lnCuiCurent = Val(Getwordnum(m.lcListaCoduriRamase, m.lnRec, ','))
|
||||
llGasitCache = .F.
|
||||
If Used(m.lcAlias) And Reccount(m.lcAlias) > 0
|
||||
Select (m.lcAlias)
|
||||
Locate For cui = m.lnCuiCurent
|
||||
llGasitCache = Found()
|
||||
Endif
|
||||
lnFaraRaspuns = m.lnFaraRaspuns + Iif(m.llGasitCache, 0, 1)
|
||||
Endfor
|
||||
Endif
|
||||
|
||||
*!* 01.08.2026 marius.mutu: un singur mesaj la final, doar cand au ramas coduri fara verdict (nici de la ANAF, nici din cache)
|
||||
If m.lnFaraRaspuns > 0 And !Empty(This.cMesajANAF)
|
||||
AMESSAGEBOX(This.cMesajANAF + Chr(13) + Chr(10) + Alltrim(Str(m.lnFaraRaspuns)) + ' coduri fiscale nu au putut fi verificate.', 0 + 48, _Screen.Caption)
|
||||
Endif
|
||||
|
||||
If Used(m.lcAlias) And Reccount(m.lcAlias) > 0
|
||||
This.SalveazaIstoricDinCursor(m.lcAlias, gnIdUtil)
|
||||
Endif
|
||||
|
||||
* criteriul 9: totalul randurilor completate din cache (CACHE si CACHE_INDISP), o singura linie in goLog
|
||||
If Used(m.lcAlias) And Reccount(m.lcAlias) > 0
|
||||
Select (m.lcAlias)
|
||||
lnCache = 0
|
||||
lnCacheIndisp = 0
|
||||
Scan For Left(Nvl(sursa, ''), 5) == 'CACHE'
|
||||
If Upper(Alltrim(sursa)) == 'CACHE_INDISP'
|
||||
lnCacheIndisp = m.lnCacheIndisp + 1
|
||||
Else
|
||||
lnCache = m.lnCache + 1
|
||||
Endif
|
||||
Select (m.lcAlias)
|
||||
Endscan
|
||||
If m.lnCache + m.lnCacheIndisp > 0
|
||||
goLog.Log('cache total=' + Transform(m.lnCache + m.lnCacheIndisp) + ' cache=' + Transform(m.lnCache) + ' cache_indisp=' + Transform(m.lnCacheIndisp), 'VerificaListaCIF')
|
||||
Endif
|
||||
Endif
|
||||
|
||||
Return m.lcAlias
|
||||
Endfunc && AnafPlatitorTVA
|
||||
|
||||
*************************************
|
||||
*** Normalizeaza codurile fiscale dintr-un cursor in forma tcCursorListaCIF (cod_fiscal C(30)[, data D]),
|
||||
*** dupa acelasi tipar ca ANAF_SincronWebService_PlatitorTva (cod tara RO, doar cifre, <=10 caractere).
|
||||
*** Cand sursa nu are coloana data (ex. orapoarte.prg:1994/2311, cursor doar cu cod_fiscal), se
|
||||
*** foloseste tdData pentru toate randurile - acelasi fallback ca llDataCursor din functia de mai sus
|
||||
*** Intoarce un cursor nou (cod_fiscal, data, cui_n N(13)) - cui_n = 0 cand codul nu e un CUI RO valid
|
||||
*************************************
|
||||
Function NormalizeazaCoduriCursor
|
||||
Lparameters tcCursorListaCIF, tdData
|
||||
|
||||
Local loVerificareCod As "VerificareCod", lcCodFiscal, lcCodTara, lcCodFiscalFRO, lcAliasNorm, lcSelect, llDataCursor, ldDataRand, ldDataImplicit, lnCuiNorm
|
||||
lcSelect = Select()
|
||||
lcAliasNorm = 'crsCoduriNormalizate'
|
||||
Use In (Select(m.lcAliasNorm))
|
||||
Create Cursor (m.lcAliasNorm) (cod_fiscal C(30), data D, cui_n N(13))
|
||||
|
||||
ldDataImplicit = Iif(Type('tdData') = 'D' And !Empty(m.tdData), m.tdData, Date())
|
||||
llDataCursor = (Type(m.tcCursorListaCIF + '.data') = 'D')
|
||||
|
||||
loVerificareCod = Createobject("VerificareCod")
|
||||
Select (m.tcCursorListaCIF)
|
||||
Scan
|
||||
*!* 01.08.2026 marius.mutu: cursoarele sursa au cod_fiscal/data nullable - fara Nvl, insertul de mai jos pica pe coloanele not null
|
||||
lcCodFiscal = Alltrim(Nvl(cod_fiscal, ''))
|
||||
lcCodTara = loVerificareCod.GetCodTara(m.lcCodFiscal)
|
||||
lcCodFiscalFRO = Strtran(m.lcCodFiscal, m.lcCodTara, '')
|
||||
lcCodFiscalFRO = Strtran(Strtran(Strtran(m.lcCodFiscalFRO, ' ', ''), 'RO', ''), 'R', '')
|
||||
ldDataRand = Iif(m.llDataCursor And !Empty(Nvl(data, {})), Nvl(data, {}), m.ldDataImplicit)
|
||||
*!* 02.08.2026 marius.mutu: pe langa formatul de baza, si cifra de control (VALIDARE_CIF) - un CIF invalid nu are ce cauta nici in cache, nici la ANAF
|
||||
lnCuiNorm = 0
|
||||
If m.lcCodTara = 'RO' And Isdigit(m.lcCodFiscalFRO) And Len(m.lcCodFiscalFRO) <= 10 ;
|
||||
And Val(m.lcCodFiscalFRO) <> 0 And loVerificareCod.VALIDARE_CIF(m.lcCodFiscalFRO)
|
||||
lnCuiNorm = Int(Val(m.lcCodFiscalFRO))
|
||||
Endif
|
||||
Insert Into (m.lcAliasNorm) (cod_fiscal, data, cui_n) Values (m.lcCodFiscal, m.ldDataRand, m.lnCuiNorm)
|
||||
Select (m.tcCursorListaCIF)
|
||||
Endscan
|
||||
|
||||
Select (m.lcSelect)
|
||||
Return m.lcAliasNorm
|
||||
Endfunc && NormalizeazaCoduriCursor
|
||||
|
||||
*
|
||||
Function ANAF_SincronWebService_PlatitorTva
|
||||
Lparameters tcCursorListaCIF, tdData, tcAlias
|
||||
@@ -1899,7 +2141,7 @@ Define Class VerificareANAF As Custom
|
||||
Try
|
||||
loHTTP = Createobject('Microsoft.XMLHTTP') && 04.07.2016
|
||||
Catch To loEx
|
||||
AMESSAGEBOX(loEx.Message, 0 + 16, _Screen.Caption)
|
||||
This.cMesajANAF = loEx.Message
|
||||
Endtry
|
||||
Endif
|
||||
If Type('loHTTP') <> 'O'
|
||||
@@ -1941,7 +2183,8 @@ Define Class VerificareANAF As Custom
|
||||
lcCodFiscalFRO = Strtran(m.lcCodFiscal, m.lcCodTara, '')
|
||||
lcCodFiscalFRO = Strtran(Strtran(Strtran(m.lcCodFiscalFRO, ' ', ''), 'RO', ''), 'R', '')
|
||||
|
||||
If m.llRO AND (Isdigit(m.lcCodFiscalFRO) and Len(m.lcCodFiscalFRO) <= 10)
|
||||
*!* 02.08.2026 marius.mutu: acelasi filtru ca in NormalizeazaCoduriCursor - format de baza plus cifra de control (VALIDARE_CIF)
|
||||
If m.llRO AND (Isdigit(m.lcCodFiscalFRO) and Len(m.lcCodFiscalFRO) <= 10 and Val(m.lcCodFiscalFRO) <> 0 and loVerificareCod.VALIDARE_CIF(m.lcCodFiscalFRO))
|
||||
loCol = Createobject("empty")
|
||||
AddProperty(loCol, "cui", Int(Val(m.lcCodFiscalFRO)))
|
||||
AddProperty(loCol, "data", m.lcDataFormatted)
|
||||
@@ -1949,53 +2192,25 @@ Define Class VerificareANAF As Custom
|
||||
laCoduri[lnIdx] = loCol
|
||||
ENDIF
|
||||
Endscan && tcCursorListaCIF
|
||||
IF m.lnIdx > 0
|
||||
Dimension laCoduri(lnIdx)
|
||||
ENDIF
|
||||
|
||||
*!* 02.08.2026 marius.mutu: grup fara niciun CUI valid - nu se mai trimite cerere goala la ANAF
|
||||
IF m.lnIdx = 0
|
||||
LOOP
|
||||
ENDIF
|
||||
Dimension laCoduri(lnIdx)
|
||||
|
||||
lcSend = nfjsoncreate(@laCoduri)
|
||||
goLog.Log('lcSend: ' + m.lcSend, 'ANAF_SincronWebService_PlatitorTva')
|
||||
|
||||
lcJsonString = ''
|
||||
*!* 31.07.2026 marius.mutu: procesarea raspunsului (status+corp) mutata in ProceseazaRaspunsHTTP, mai jos
|
||||
Try
|
||||
loHTTP.Open('POST', lcServer, .F.) && !!! POST e blocat de furnizor
|
||||
loHTTP.setRequestHeader("Content-Type", "application/json;")
|
||||
loHTTP.Send(lcSend)
|
||||
If loHTTP.Status = 200
|
||||
lcJsonString = ALLTRIM(loHTTP.responseText)
|
||||
IF LEFT(m.lcJsonString,1) <> '{'
|
||||
IF 'mentenanta'$LOWER(m.lcJsonString)
|
||||
AMESSAGEBOX('Serviciul web ANAF este in mentenanta!',0+48,_screen.Caption)
|
||||
ELSE
|
||||
AMESSAGEBOX('Serviciul web ANAF nu a intors un raspuns corespunzator.!' + CHR(13) + CHR(10) + m.lcJsonString,0+48,_screen.Caption)
|
||||
ENDIF
|
||||
lcJsonString = ''
|
||||
ENDIF
|
||||
ENDIF
|
||||
lcAlias = This.ProceseazaRaspunsHTTP(loHTTP.Status, loHTTP.responseText, m.tcAlias)
|
||||
Catch To loEx
|
||||
AMESSAGEBOX(loEx.Message, 0 + 16, _Screen.Caption)
|
||||
Endtry
|
||||
This.cMesajANAF = loEx.Message
|
||||
Endtry
|
||||
*
|
||||
goLog.Log('lcJsonString: ' + m.lcJsonString, 'ANAF_SincronWebService_PlatitorTva')
|
||||
|
||||
*
|
||||
If Not Empty(m.lcJsonString)
|
||||
TRY
|
||||
loJsonObject = nfjsonread(m.lcJsonString) && nfJson from http://vfpx.codeplex.com/
|
||||
lcCodJudet = ""
|
||||
IF TYPE('loJsonObject.found_vfpsafe_[1].adresa_domiciliu_fiscal.dcod_judet') <> 'U'
|
||||
lcCodJudet = loJsonObject.found_vfpsafe_[1].adresa_domiciliu_fiscal.dcod_judet
|
||||
ENDIF
|
||||
IF !EMPTY(m.lcCodJudet)
|
||||
lcAlias = This.ParseJsonANAFv8(loJsonObject, m.tcAlias)
|
||||
ELSE
|
||||
lcMesaj = 'Serviciul web ANAF intors mesaj de eroare: ' + IIF(TYPE('loJsonObject.message') = 'C', loJsonObject.message, '')
|
||||
AMESSAGEBOX(m.lcMesaj, 0+48, _screen.Caption)
|
||||
ENDIF
|
||||
CATCH TO loEx
|
||||
AMESSAGEBOX(loEx.Message, 0 + 16, _Screen.Caption)
|
||||
ENDTRY
|
||||
Endif
|
||||
If m.lnGrup < m.lnGrupuri
|
||||
INKEY(m.lnWaitSeconds)&& astept o secunda intre interogari
|
||||
ENDIF
|
||||
@@ -2004,6 +2219,51 @@ Define Class VerificareANAF As Custom
|
||||
Return m.lcAlias
|
||||
Endfunc && ANAF_SincronWebService_PlatitorTva
|
||||
|
||||
*************************************
|
||||
*** Proceseaza UN raspuns HTTP deja primit pe calea batch (status + corp), separat de trimiterea
|
||||
*** cererii ca sa poata fi testat direct, cu status+corp fabricate, fara transport HTTP real.
|
||||
*** Corpul se citeste indiferent de status (nu doar pe 200) - ANAF poate intoarce si 404 cu corp
|
||||
*** JSON complet cand toate codurile din grup sunt inexistente (masurat 27.07.2026), la fel ca pe
|
||||
*** calea single-CUI (ANAF_VerificaCuiSingle). Un raspuns e considerat inteles cand are structura
|
||||
*** found/notFound, chiar daca found e gol (lot integral notFound); altfel ramane tacere - cursorul
|
||||
*** nu se modifica, deci codurile din grup raman fara rand in crsANAF, ca la o cadere reala de serviciu
|
||||
*************************************
|
||||
Function ProceseazaRaspunsHTTP
|
||||
Lparameters tnStatus, tcResponseText, tcAlias
|
||||
|
||||
Local lcAlias, lcJsonString, loJsonObject, loEx As Exception, lcMesaj, llRaspunsInteles
|
||||
|
||||
lcAlias = Iif(!Empty(m.tcAlias) And Type('tcAlias') = "C", m.tcAlias, "crsANAF")
|
||||
lcJsonString = Alltrim(Nvl(m.tcResponseText, ''))
|
||||
goLog.Log('tnStatus: ' + Transform(m.tnStatus) + ' lcJsonString: ' + m.lcJsonString, 'ANAF_SincronWebService_PlatitorTva')
|
||||
|
||||
If Empty(m.lcJsonString) Or Left(m.lcJsonString, 1) <> '{'
|
||||
If !Empty(m.lcJsonString)
|
||||
IF 'mentenanta'$LOWER(m.lcJsonString)
|
||||
This.cMesajANAF = 'Serviciul web ANAF este in mentenanta!'
|
||||
ELSE
|
||||
This.cMesajANAF = 'Serviciul web ANAF nu a intors un raspuns corespunzator.'
|
||||
ENDIF
|
||||
Endif
|
||||
Return m.lcAlias && tacere: fara corp folosibil, cursorul ramane neschimbat
|
||||
Endif
|
||||
|
||||
Try
|
||||
loJsonObject = nfjsonread(m.lcJsonString) && nfJson from http://vfpx.codeplex.com/
|
||||
llRaspunsInteles = (Type('loJsonObject') = 'O' And Pemstatus(m.loJsonObject, 'found_vfpsafe_', 5))
|
||||
If m.llRaspunsInteles
|
||||
lcAlias = This.ParseJsonANAFv8(m.loJsonObject, m.tcAlias)
|
||||
Else
|
||||
lcMesaj = 'Serviciul web ANAF a intors mesaj de eroare: ' + IIF(TYPE('loJsonObject.message') = 'C', loJsonObject.message, '')
|
||||
This.cMesajANAF = m.lcMesaj
|
||||
Endif
|
||||
Catch To loEx
|
||||
This.cMesajANAF = loEx.Message
|
||||
Endtry
|
||||
|
||||
Return m.lcAlias
|
||||
Endfunc && ProceseazaRaspunsHTTP
|
||||
|
||||
*************************************
|
||||
*** Parseaza obiectul cu raspunsul de la ANAF si creeaza cursorul crsANAF
|
||||
*** intoarce numele cursorului creat
|
||||
@@ -2023,7 +2283,8 @@ Define Class VerificareANAF As Custom
|
||||
dataInceputTvaInc D, dataSfarsitTvaInc D, dataActualizareTvaInc D, dataPublicareTvaInc D, tipActTvaInc C(100), statusTvaIncasare L, dataInactivare D, dataReactivare D, dataPublicare D, dataRadiere D, statusInactivi L, ;
|
||||
dataInceputSplitTVA D, dataAnulareSplitTVA D, statusSplitTVA L, ;
|
||||
tva L, tvaincasare L, splittva L, inactiv L, ;
|
||||
mesaj V(100), judet V(100), strada V(100), nr V(20), localitate V(100), Bloc V(20), scara V(20), etaj V(20), apart V(20))
|
||||
mesaj V(100), judet V(100), strada V(100), nr V(20), localitate V(100), Bloc V(20), scara V(20), etaj V(20), apart V(20), ;
|
||||
sursa C(20), data_sursa D)
|
||||
Endif
|
||||
|
||||
If !Isnull(loJsonObject)
|
||||
@@ -2126,7 +2387,8 @@ Define Class VerificareANAF As Custom
|
||||
loDate.splittva = loDate.statusSplitTVA
|
||||
loDate.inactiv = loDate.statusInactivi
|
||||
loDate.mesaj = loDate.mesaj_ScpTVA
|
||||
|
||||
loDate.sursa = 'ANAF'
|
||||
|
||||
IF !EMPTY(NVL(loDate.cui, 0))
|
||||
Insert Into (m.lcAlias) FROM NAME loDate
|
||||
ENDIF
|
||||
@@ -2139,7 +2401,8 @@ Define Class VerificareANAF As Custom
|
||||
SCATTER NAME loDate MEMO BLANK
|
||||
|
||||
loDate.cui = m.lnCUI
|
||||
|
||||
loDate.sursa = 'ANAF'
|
||||
|
||||
IF !EMPTY(NVL(loDate.cui, 0))
|
||||
Insert Into (m.lcAlias) FROM NAME loDate
|
||||
ENDIF
|
||||
@@ -2381,6 +2644,249 @@ Define Class VerificareANAF As Custom
|
||||
Return loAdresa
|
||||
Endproc
|
||||
|
||||
*************************************
|
||||
*** Parcurge un cursor in forma crsANAF si salveaza fiecare rand in ISTORIC_CODURI_FISCALE
|
||||
*** prin pack_parteneri.save_istoric_cod_fiscal (26 parametri); commit din 100 in 100 si la final
|
||||
*** Sare peste randurile provenite din cache (sursa incepe cu 'CACHE') - au fost deja salvate
|
||||
*** Intoarce numarul de randuri salvate cu succes
|
||||
*************************************
|
||||
Function SalveazaIstoricDinCursor
|
||||
Lparameters tcAlias, tnIdUtil
|
||||
|
||||
Local lnSalvate, lcSelect, lcSqlIstoric, lnRecnoInit
|
||||
Private pcCodFiscal, pcFirma, pcAdresa, pcJudet, pcRegCom, pcCodPostal, pcTelefon, pcFax, pcDataTvamfin, ;
|
||||
pnPlatitorTvaMfin, pcStare, pnPlatitorTvaVies, pnInterogareVies, pnIdUtil, ;
|
||||
pnInactiv, pnTvaIncasare, pnSplitTva, ;
|
||||
pdInceputScpTva, pdSfarsitScpTva, pdAnulImpScpTva, pdInceputTvaInc, pdSfarsitTvaInc, ;
|
||||
pdInactivare, pdReactivare, pdInceputSplitTva, pdAnulareSplitTva, pnDinCache
|
||||
|
||||
lnSalvate = 0
|
||||
If Empty(m.tcAlias) Or !Used(m.tcAlias)
|
||||
Return m.lnSalvate
|
||||
Endif
|
||||
|
||||
lcSelect = Select()
|
||||
pnIdUtil = m.tnIdUtil
|
||||
|
||||
Select (m.tcAlias)
|
||||
lnRecnoInit = Recno()
|
||||
Scan For cui <> 0 And Left(Nvl(sursa, ''), 5) <> 'CACHE'
|
||||
pcCodFiscal = Transform(cui)
|
||||
pcFirma = Alltrim(Nvl(firma, ''))
|
||||
pcAdresa = Alltrim(Nvl(adresa, ''))
|
||||
pcJudet = Alltrim(Nvl(judet, ''))
|
||||
pcRegCom = Alltrim(Nvl(nrRegCom, ''))
|
||||
pcCodPostal = ''
|
||||
pcTelefon = ''
|
||||
pcFax = ''
|
||||
pcDataTvamfin = ''
|
||||
pnPlatitorTvaMfin = 0
|
||||
pcStare = ''
|
||||
pnPlatitorTvaVies = 0
|
||||
pnInterogareVies = 0
|
||||
pnInactiv = Iif(Nvl(inactiv, .F.), 1, 0)
|
||||
pnTvaIncasare = Iif(Nvl(tvaincasare, .F.), 1, 0)
|
||||
pnSplitTva = Iif(Nvl(splittva, .F.), 1, 0)
|
||||
pdInceputScpTva = data_inceput_ScpTVA
|
||||
pdSfarsitScpTva = data_sfarsit_ScpTVA
|
||||
pdAnulImpScpTva = data_anul_imp_ScpTVA
|
||||
pdInceputTvaInc = dataInceputTvaInc
|
||||
pdSfarsitTvaInc = dataSfarsitTvaInc
|
||||
pdInactivare = dataInactivare
|
||||
pdReactivare = dataReactivare
|
||||
pdInceputSplitTva = dataInceputSplitTVA
|
||||
pdAnulareSplitTva = dataAnulareSplitTVA
|
||||
*!* 01.08.2026 marius.mutu: pnDinCache=1 cand randul vine din cache - opreste improspatarea DATAORAV_ANAF pe ecoul din cache, jos in pachet
|
||||
pnDinCache = Iif(Left(Nvl(sursa, ''), 5) == 'CACHE', 1, 0)
|
||||
|
||||
lcSqlIstoric = "begin pack_parteneri.save_istoric_cod_fiscal(?pcCodFiscal,?pcFirma,?pcAdresa,?pcJudet,?pcRegCom,?pcCodPostal,?pcTelefon,?pcFax,?pcDataTvamfin,?pnPlatitorTvaMfin,?pcStare," + ;
|
||||
"?pnPlatitorTvaVies,?pnInterogareVies,?pnIdUtil,?pnInactiv,?pnTvaIncasare,?pnSplitTva,?pdInceputScpTva,?pdSfarsitScpTva," + ;
|
||||
"?pdAnulImpScpTva,?pdInceputTvaInc,?pdSfarsitTvaInc,?pdInactivare,?pdReactivare,?pdInceputSplitTva,?pdAnulareSplitTva,?pnDinCache); end;"
|
||||
If goExecutor.oExecuta(m.lcSqlIstoric)
|
||||
lnSalvate = m.lnSalvate + 1
|
||||
If Mod(m.lnSalvate, 100) = 0
|
||||
goExecutor.oExecuta('COMMIT')
|
||||
Endif
|
||||
Endif
|
||||
Select (m.tcAlias)
|
||||
Endscan
|
||||
|
||||
If m.lnSalvate > 0
|
||||
goExecutor.oExecuta('COMMIT')
|
||||
Endif
|
||||
|
||||
*!* 01.08.2026 marius.mutu: Scan lasa pointerul pe EOF - il pun la loc, ca sa nu afectez apelantul
|
||||
Select (m.tcAlias)
|
||||
Try
|
||||
Go m.lnRecnoInit
|
||||
Catch
|
||||
Go Top
|
||||
Endtry
|
||||
|
||||
Select (m.lcSelect)
|
||||
Return m.lnSalvate
|
||||
Endfunc && SalveazaIstoricDinCursor
|
||||
|
||||
*************************************
|
||||
*** Citeste din ISTORIC_CODURI_FISCALE ultima verificare proaspata (pe DATAORAV_ANAF) pentru
|
||||
*** codurile din tcListaCoduriN (normalizate, numerice, separate prin virgula) si calculeaza
|
||||
*** in SQL, la tdData, verdictele din intervale (platitor TVA, TVA la incasare, split TVA, inactiv)
|
||||
*** Adauga randurile in tcAlias (cursor in forma crsANAF + sursa/data_sursa), creandu-l daca lipseste
|
||||
*** tcSursa (optional, implicit 'CACHE') eticheteaza randurile inserate - 'CACHE' sau 'CACHE_INDISP'
|
||||
*** Un rand NU se intoarce cand tdData e inainte de inceputul unui interval cunoscut (scpTVA/TVAINC/
|
||||
*** inactivare) - ANAF intoarce o singura perioada, nu istoricul complet, deci pentru o data anterioara
|
||||
*** primei perioade memorate cache-ul nu poate afirma "nu era" - codul ramane netratat, merge la ANAF
|
||||
*** Intoarce numele cursorului; ramane gol, fara eroare, cand nu gaseste nimic
|
||||
*************************************
|
||||
Function CitesteIstoricPentruCoduri
|
||||
Lparameters tcListaCoduriN, tdData, tcAlias, tcSursa
|
||||
|
||||
Local lcAlias, lcCursorIstoric, lcSql, ldData, lnZileCache, lcSelect, lcSursa, lcCondCod, lnTotalCod, lnTranse, lnTransa, lnI, lcTransa
|
||||
*!* 30.07.2026 marius.mutu: pdDataCache/pnZileCache Private, nu Local, ca sa fie vizibile in goExecutor.oExecuta la bind
|
||||
Private pdDataCache, pnZileCache
|
||||
lcAlias = Iif(!Empty(m.tcAlias) And Type('tcAlias') = "C", m.tcAlias, "crsANAF")
|
||||
ldData = Iif(Type('tdData') = 'D' And !Empty(m.tdData), m.tdData, Date())
|
||||
lcSursa = Iif(!Empty(m.tcSursa) And Type('tcSursa') = 'C', Upper(Alltrim(m.tcSursa)), 'CACHE')
|
||||
pdDataCache = m.ldData
|
||||
lcSelect = Select()
|
||||
|
||||
If !Used(m.lcAlias)
|
||||
*!* 31.07.2026 marius.mutu: aceeasi forma ca crsANAF din ParseJsonANAFv8 - Null pe cele 9 campuri de data muta problema in ParseJsonANAFv8 (SCATTER/aritmetica pe date); NULL-ul din Oracle e tratat cu Nvl la Insert Into, mai jos
|
||||
Create Cursor (m.lcAlias) (cui N(13), data D, denumire V(100), firma V(100), adresa C(244), nrRegCom C(30), scpTVA L, data_inceput_ScpTVA D, data_sfarsit_ScpTVA D, data_anul_imp_ScpTVA D, mesaj_ScpTVA C(244), ;
|
||||
dataInceputTvaInc D, dataSfarsitTvaInc D, dataActualizareTvaInc D, dataPublicareTvaInc D, tipActTvaInc C(100), statusTvaIncasare L, dataInactivare D, dataReactivare D, dataPublicare D, dataRadiere D, statusInactivi L, ;
|
||||
dataInceputSplitTVA D, dataAnulareSplitTVA D, statusSplitTVA L, ;
|
||||
tva L, tvaincasare L, splittva L, inactiv L, ;
|
||||
mesaj V(100), judet V(100), strada V(100), nr V(20), localitate V(100), Bloc V(20), scara V(20), etaj V(20), apart V(20), ;
|
||||
sursa C(20), data_sursa D)
|
||||
Endif
|
||||
|
||||
If Empty(m.tcListaCoduriN)
|
||||
Select (m.lcSelect)
|
||||
Return m.lcAlias
|
||||
Endif
|
||||
|
||||
lnZileCache = This.ZileCache()
|
||||
pnZileCache = m.lnZileCache
|
||||
lcCursorIstoric = 'crsIstoricCacheTemp'
|
||||
Use In (Select(m.lcCursorIstoric))
|
||||
|
||||
*!* 02.08.2026 marius.mutu: transe de maxim 1000 coduri legate cu OR - peste 1000 elemente "in (...)" da ORA-01795
|
||||
lnTotalCod = Getwordcount(m.tcListaCoduriN, ',')
|
||||
lnTranse = Ceiling(m.lnTotalCod / 1000)
|
||||
lcCondCod = ''
|
||||
For lnTransa = 1 To m.lnTranse
|
||||
lcTransa = ''
|
||||
For lnI = (m.lnTransa - 1) * 1000 + 1 To Min(m.lnTransa * 1000, m.lnTotalCod)
|
||||
lcTransa = m.lcTransa + Iif(Empty(m.lcTransa), '', ',') + Getwordnum(m.tcListaCoduriN, m.lnI, ',')
|
||||
Endfor
|
||||
lcCondCod = m.lcCondCod + Iif(Empty(m.lcCondCod), '', ' or ') + 'cod_fiscal_n in (' + m.lcTransa + ')'
|
||||
Endfor
|
||||
If m.lnTranse > 1
|
||||
lcCondCod = '(' + m.lcCondCod + ')'
|
||||
Endif
|
||||
|
||||
*!* 01.08.2026 marius.mutu: v_tvainc - margine exclusiva (data_sfarsit_tvainc - 1), aliniata cu pack_roartvai; ground truth rtvai_istoric confirma [inceput,sfarsit)
|
||||
*!* 02.08.2026 marius.mutu: randul curent se alege pe dataorav_anaf desc - dupa fuziunea istoricelor, ID-ul nu mai urmeaza ordinea cronologica
|
||||
TEXT To lcSql TEXTMERGE Noshow
|
||||
select cod_fiscal_n, firma, adresa, judet, regcom, dataorav_anaf,
|
||||
data_inceput_scptva, data_sfarsit_scptva, data_anul_imp_scptva,
|
||||
data_inceput_tvainc, data_sfarsit_tvainc, data_inactivare, data_reactivare,
|
||||
data_inceput_splittva, data_anulare_splittva,
|
||||
case when ?pdDataCache between data_inceput_scptva and nvl(data_sfarsit_scptva, to_date('29991231','yyyymmdd')) then 1 else 0 end as v_scptva,
|
||||
case when ?pdDataCache between data_inceput_tvainc and nvl(data_sfarsit_tvainc - 1, to_date('29991231','yyyymmdd')) then 1 else 0 end as v_tvainc,
|
||||
case when ?pdDataCache between data_inceput_splittva and nvl(data_anulare_splittva, to_date('29991231','yyyymmdd')) then 1 else 0 end as v_splittva,
|
||||
case when data_inactivare is not null and ?pdDataCache >= data_inactivare and (data_reactivare is null or ?pdDataCache < data_reactivare) then 1 else 0 end as v_inactiv
|
||||
from (select i.*, row_number() over (partition by cod_fiscal_n order by dataorav_anaf desc, id desc) as rn
|
||||
from istoric_coduri_fiscale i
|
||||
where <<m.lcCondCod>>
|
||||
and dataorav_anaf is not null
|
||||
and sysdate - dataorav_anaf <= ?pnZileCache)
|
||||
where rn = 1
|
||||
and (data_inceput_scptva is null or ?pdDataCache >= data_inceput_scptva)
|
||||
and (data_inceput_tvainc is null or ?pdDataCache >= data_inceput_tvainc)
|
||||
and (data_inactivare is null or ?pdDataCache >= data_inactivare)
|
||||
ENDTEXT
|
||||
|
||||
If goExecutor.oExecuta(m.lcSql, m.lcCursorIstoric) And Used(m.lcCursorIstoric)
|
||||
Select (m.lcCursorIstoric)
|
||||
Scan
|
||||
*!* 31.07.2026 marius.mutu: campurile din VALUES calificate cu alias literal crsIstoricCacheTemp - necalificat da eroare 12 (inghitita de ON ERROR), Insert Into ramanea mereu gol
|
||||
Insert Into (m.lcAlias) (cui, data, denumire, firma, adresa, judet, nrRegCom, ;
|
||||
data_inceput_ScpTVA, data_sfarsit_ScpTVA, data_anul_imp_ScpTVA, ;
|
||||
dataInceputTvaInc, dataSfarsitTvaInc, dataInactivare, dataReactivare, ;
|
||||
dataInceputSplitTVA, dataAnulareSplitTVA, ;
|
||||
scpTVA, statusTvaIncasare, statusSplitTVA, statusInactivi, ;
|
||||
tva, tvaincasare, splittva, inactiv, sursa, data_sursa) Values ;
|
||||
(crsIstoricCacheTemp.cod_fiscal_n, m.ldData, Nvl(crsIstoricCacheTemp.firma, ''), Nvl(crsIstoricCacheTemp.firma, ''), Nvl(crsIstoricCacheTemp.adresa, ''), Nvl(crsIstoricCacheTemp.judet, ''), Nvl(crsIstoricCacheTemp.regcom, ''), ;
|
||||
Nvl(crsIstoricCacheTemp.data_inceput_scptva, {}), Nvl(crsIstoricCacheTemp.data_sfarsit_scptva, {}), Nvl(crsIstoricCacheTemp.data_anul_imp_scptva, {}), ;
|
||||
Nvl(crsIstoricCacheTemp.data_inceput_tvainc, {}), Nvl(crsIstoricCacheTemp.data_sfarsit_tvainc, {}), Nvl(crsIstoricCacheTemp.data_inactivare, {}), Nvl(crsIstoricCacheTemp.data_reactivare, {}), ;
|
||||
Nvl(crsIstoricCacheTemp.data_inceput_splittva, {}), Nvl(crsIstoricCacheTemp.data_anulare_splittva, {}), ;
|
||||
(crsIstoricCacheTemp.v_scptva = 1), (crsIstoricCacheTemp.v_tvainc = 1), (crsIstoricCacheTemp.v_splittva = 1), (crsIstoricCacheTemp.v_inactiv = 1), ;
|
||||
(crsIstoricCacheTemp.v_scptva = 1), (crsIstoricCacheTemp.v_tvainc = 1), (crsIstoricCacheTemp.v_splittva = 1), (crsIstoricCacheTemp.v_inactiv = 1), m.lcSursa, crsIstoricCacheTemp.dataorav_anaf)
|
||||
Endscan
|
||||
Use In (Select(m.lcCursorIstoric))
|
||||
Endif
|
||||
|
||||
Select (m.lcSelect)
|
||||
Return m.lcAlias
|
||||
Endfunc && CitesteIstoricPentruCoduri
|
||||
|
||||
*************************************
|
||||
*** Citeste din OPTIUNI (per schema) ordinea traseelor de verificare ANAF/cache
|
||||
*** tcTraseu: 'UNIC' (un singur cod) sau 'MASA' (lot); implicit cand randul lipseste din OPTIUNI:
|
||||
*** 'ANAF,CACHE' pe UNIC, 'CACHE,ANAF' pe MASA
|
||||
*************************************
|
||||
Function OrdineCache
|
||||
Lparameters tcTraseu
|
||||
|
||||
Local lcTraseu, lcVarName, lcImplicit, lcSql, lcCursor, lcOrdine, lcSelect
|
||||
*!* 31.07.2026 marius.mutu: lcSelect salvat/restaurat - fara asta apelantul ramanea cu work area-ul schimbat
|
||||
lcSelect = Select()
|
||||
lcTraseu = Upper(Alltrim(Nvl(m.tcTraseu, '')))
|
||||
lcImplicit = Iif(m.lcTraseu == 'MASA', 'CACHE,ANAF', 'ANAF,CACHE')
|
||||
lcVarName = 'ANAFCACHEORDINE_' + Iif(m.lcTraseu == 'MASA', 'MASA', 'UNIC')
|
||||
lcCursor = 'crsOptiuneOrdineCache'
|
||||
lcOrdine = ''
|
||||
|
||||
lcSql = "select varvalue from optiuni where varname = '" + m.lcVarName + "'"
|
||||
If goExecutor.oExecuta(m.lcSql, m.lcCursor) And Used(m.lcCursor)
|
||||
If Reccount(m.lcCursor) > 0
|
||||
lcOrdine = Upper(Strtran(Alltrim(Nvl(&lcCursor..varvalue, '')), ' ', ''))
|
||||
Endif
|
||||
Use In (Select(m.lcCursor))
|
||||
Endif
|
||||
|
||||
Select (m.lcSelect)
|
||||
Return Iif(Empty(m.lcOrdine), m.lcImplicit, m.lcOrdine)
|
||||
Endfunc && OrdineCache
|
||||
|
||||
*************************************
|
||||
*** Citeste din OPTIUNI (per schema) vechimea maxima a cache-ului, in zile, masurata pe DATAORAV_ANAF
|
||||
*** Implicit cand randul lipseste din OPTIUNI: 30
|
||||
*************************************
|
||||
Function ZileCache
|
||||
Local lcCursor, lcSql, lnZile, lcSelect
|
||||
*!* 31.07.2026 marius.mutu: lcSelect salvat/restaurat - acelasi defect ca la OrdineCache
|
||||
lcSelect = Select()
|
||||
lcCursor = 'crsOptiuneZileCache'
|
||||
lnZile = 30
|
||||
|
||||
lcSql = "select varvalue from optiuni where varname = 'ANAFCACHEZILE'"
|
||||
If goExecutor.oExecuta(m.lcSql, m.lcCursor) And Used(m.lcCursor)
|
||||
If Reccount(m.lcCursor) > 0 And !Empty(Alltrim(Nvl(&lcCursor..varvalue, '')))
|
||||
lnZile = Val(Alltrim(&lcCursor..varvalue))
|
||||
Endif
|
||||
Use In (Select(m.lcCursor))
|
||||
Endif
|
||||
|
||||
If m.lnZile <= 0
|
||||
lnZile = 30
|
||||
Endif
|
||||
|
||||
Select (m.lcSelect)
|
||||
Return m.lnZile
|
||||
Endfunc && ZileCache
|
||||
|
||||
|
||||
Enddefine && VerificareANAF
|
||||
|
||||
|
||||
@@ -371,7 +371,7 @@ Define Class ExportEFactura As Custom
|
||||
lcTextAditional = m.lcTextAditional + Iif(!Empty(m.lcTextAditional), ' # ', '') + "Taxare inversa"
|
||||
ENDIF
|
||||
|
||||
IF !EMPTY(NVL(loDate.curs,0)) AND ATC('curs', m.lcTextAditional) = 0
|
||||
IF loDate.in_valuta = 1 AND !EMPTY(NVL(loDate.curs,0)) AND ATC('curs', m.lcTextAditional) = 0
|
||||
lcTextAditional = m.lcTextAditional + Iif(!Empty(m.lcTextAditional), ' # ', '') + "Curs: " + ALLTRIM(STR(loDate.curs, 10,4)) + " RON/" + STRTRAN(ALLTRIM(Nvl(loDate.cValuta, '')),'EURO', 'EUR',1,1,1)
|
||||
ENDIF
|
||||
|
||||
|
||||
@@ -2434,7 +2434,7 @@ DEFINE CLASS gridutils AS form
|
||||
PROCEDURE copytoexcel
|
||||
*!* LPARAMETERS tcXLSFile, tcSheet, tvWorkArea, tcExcelFieldList, tcTableFieldList, tcTableForExpr
|
||||
#DEFINE ALPHANUMERICCHR "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz1234567890"
|
||||
LOCAL lnCounter, loColumn, lcXLSFile, lcSheetName, lcAliasWas, lcGridAlias, ;
|
||||
LOCAL lnCounter, lnOrder, laOrder, loColumn, lcXLSFile, lcSheetName, lcAliasWas, lcGridAlias, ;
|
||||
lcExcelFieldList, lcTableFieldList, lcTableForExpression, loHeaderObject, ;
|
||||
lcFileName, lcAction, lcPath, loExcelApp, loWorkBook, lcKeyName
|
||||
m.lcXLSFile = "C:\" + SYS(2015) + ".xls"
|
||||
@@ -2445,8 +2445,15 @@ DEFINE CLASS gridutils AS form
|
||||
*!* m.lcTableForExpression = FILTER(this.gridobject.recordsource)
|
||||
m.lcSheetName = "Sheet1"
|
||||
STORE "" TO m.lcExcelFieldList, m.lcTableFieldList
|
||||
*!* coloanele se exporta in ordinea de afisare din grid (ColumnOrder), nu in ordinea de creare
|
||||
DIMENSION laOrder[MAX(THIS.gridobject.COLUMNCOUNT, 1), 2]
|
||||
FOR m.lnCounter = 1 TO THIS.gridobject.COLUMNCOUNT
|
||||
m.loColumn = THIS.gridobject.COLUMNS(m.lnCounter)
|
||||
laOrder[m.lnCounter, 1] = THIS.gridobject.COLUMNS(m.lnCounter).COLUMNORDER
|
||||
laOrder[m.lnCounter, 2] = m.lnCounter
|
||||
ENDFOR
|
||||
=ASORT(laOrder)
|
||||
FOR m.lnOrder = 1 TO THIS.gridobject.COLUMNCOUNT
|
||||
m.loColumn = THIS.gridobject.COLUMNS(laOrder[m.lnOrder, 2])
|
||||
IF m.loColumn.VISIBLE AND m.loColumn.WIDTH > 0
|
||||
m.loHeaderObject = m.loColumn.CONTROLS(1)
|
||||
m.lcExcelFieldList = m.lcExcelFieldList + IIF(!EMPTY(m.lcExcelFieldList), ',', '') ;
|
||||
|
||||
@@ -10,7 +10,15 @@ $dir = [System.IO.Path]::GetDirectoryName($Prg)
|
||||
$tmpPrg = Join-Path $dir '_compile_tmp.prg'
|
||||
# prg temporar care compileaza target-ul (COMPILE cu variabila; forma cu literal in ghilimele da eroare)
|
||||
Set-Content -Path $tmpPrg -Value ("lcT = `"$Prg`"`r`nCOMPILE (lcT)`r`nQUIT`r`n") -Encoding ascii
|
||||
Get-Process vfp9 -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
|
||||
# omoara doar vfp9 proprii (linia de comanda contine folderul testului), nu instante straine
|
||||
function Stop-VfpProprii([string]$Marker) {
|
||||
Get-CimInstance Win32_Process -Filter "Name='vfp9.exe'" -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
if ($_.CommandLine -and $_.CommandLine.ToLower().Contains($Marker.ToLower())) {
|
||||
Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
}
|
||||
Stop-VfpProprii $dir
|
||||
Start-Sleep -Milliseconds 500
|
||||
if (Test-Path $Fxp) { [System.IO.File]::Delete($Fxp) }
|
||||
|
||||
@@ -48,7 +56,7 @@ foreach ($try in 1..3) {
|
||||
Start-Sleep -Milliseconds 300
|
||||
}
|
||||
Start-Sleep -Seconds 3
|
||||
Get-Process vfp9 -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
|
||||
Stop-VfpProprii $dir
|
||||
Start-Sleep -Seconds 1
|
||||
if (Test-Path $Fxp) { $ok = $true; break }
|
||||
}
|
||||
|
||||
@@ -4,5 +4,11 @@
|
||||
* (capcana l: CREATEOBJECT/ADDPROPERTY nu merg corect apelate dintr-o procedura in acest runtime).
|
||||
FUNCTION caut_valuta
|
||||
LPARAMETERS tnPornire, tlDesktop, tlFaraMonedaNationala
|
||||
LOCAL loRezultat
|
||||
IF TYPE('goMockValutaCoada') = 'O' AND !ISNULL(goMockValutaCoada) AND goMockValutaCoada.Count > 0
|
||||
loRezultat = goMockValutaCoada.Item(1)
|
||||
goMockValutaCoada.Remove(1)
|
||||
RETURN loRezultat
|
||||
ENDIF
|
||||
RETURN goMockValuta
|
||||
ENDFUNC
|
||||
|
||||
50
utile/Teste/achizitie_import/mock_cauta_alfa_tva11.prg
Normal file
50
utile/Teste/achizitie_import/mock_cauta_alfa_tva11.prg
Normal file
@@ -0,0 +1,50 @@
|
||||
* mock_cauta_alfa_tva11.prg - shadow PROCEDURE cauta_alfa (COMUN\programe\cauta_alfa.prg) DOAR
|
||||
* pentru testul de reproducere TVA 11% pe explicatia TVA din grid (do_modifica_explicatie_tva,
|
||||
* COMUN\clase\ointroduceri.vcx). Acelasi motiv ca mock_cauta_alfa_dialog.prg (cauta_alfa real
|
||||
* populeaza cursorul din Oracle prin gencursor/CursorAdapter - nemock-uibil prin goExecutor) -
|
||||
* vezi acel fisier pentru detalii complete despre flux. Aici simplificat la modul SINGLE-SELECT:
|
||||
* do_modifica_explicatie_tva nu trimite tnTipReturn, deci cauta_alfa il impune 0 (obiect scatter
|
||||
* pe randul curent, lAles=.F.) - submit-ul e echivalentul unui dublu-click pe randul dialogului
|
||||
* (bind dblClick->do_termin activ doar in modul single-select, cauta_alfa_forms.vc2:652
|
||||
* "If !Thisform.lales"), fara nevoie de marcaj (cAles).
|
||||
*
|
||||
* Control test (setat de testul principal INAINTE de fiecare apel):
|
||||
* goDlgTva11 - formularul REAL cauta_alfa_form, pre-construit in main (capcana l:
|
||||
* CREATEOBJECT dintr-o procedura da obiect stricat in acest runtime headless)
|
||||
* gcTestTvaAlege - denumirea randului de ales (coloana "denumire" a cursorului dialogului)
|
||||
|
||||
Procedure cauta_alfa
|
||||
Parameters tcselect,tcfiltru,tcschema,tcorder,tccoloana,tcTitlu,tcTitluColoane, ;
|
||||
tcNume_Proc,tl_AllInList,tcFiltruOriginal,tcPrimaColoana, tnPornire, tnTipReturn, ;
|
||||
tcIdColumn, tlDesktop, tcGroup, tcGridDynamicBackColor, tcGridToolTip, tlModParam, tcStringCriterii, ;
|
||||
tcProceduraVerifica, tcProceduraCopiaza,tcLocate
|
||||
|
||||
LOCAL lcCursor, oReturnScattObj
|
||||
|
||||
lcCursor = goDlgTva11.crs_cursor
|
||||
|
||||
SELECT (lcCursor)
|
||||
LOCATE FOR ALLTRIM(denumire) == ALLTRIM(gcTestTvaAlege)
|
||||
IF !FOUND()
|
||||
GO TOP
|
||||
ENDIF
|
||||
IF TYPE('gcUILog') = 'C'
|
||||
DO HarnessLog WITH 'MOCK cauta_alfa(explicatie tva) pozitionat pe [' + ALLTRIM(denumire) + '] id_jtva_coloana=' + TRANSFORM(id_jtva_coloana) + ' cota_tva=' + TRANSFORM(cota_tva)
|
||||
ENDIF
|
||||
|
||||
*-- echivalentul dublu-click pe randul dialogului (submit direct, mod single-select):
|
||||
*-- butonul OK REAL (_frm_base.do_termin: gnButon=1, Release oForm_cautare)
|
||||
goDlgTva11.do_termin()
|
||||
DOEVENTS FORCE
|
||||
|
||||
*-- de aici incolo: cod IDENTIC cu cauta_alfa.prg real (tnTipReturn=0 implicit) - SCATTER
|
||||
*-- pe randul curent al cursorului (NU se mai atinge oForm_cautare, Release-uit mai sus)
|
||||
SELECT (lcCursor)
|
||||
IF gnButon = 1
|
||||
SCATTER NAME oReturnScattObj MEMO
|
||||
ELSE
|
||||
SCATTER NAME oReturnScattObj MEMO BLANK
|
||||
ENDIF
|
||||
RETURN oReturnScattObj
|
||||
|
||||
Endproc && cauta_alfa (shadow test tva11)
|
||||
19
utile/Teste/achizitie_import/mock_oscrie_in_fisiere.prg
Normal file
19
utile/Teste/achizitie_import/mock_oscrie_in_fisiere.prg
Normal file
@@ -0,0 +1,19 @@
|
||||
* mock_oscrie_in_fisiere.prg - inlocuieste oscrie_in_fisiere (COMUN\programe\oscrie_in_fisiere.prg)
|
||||
* in testul e2e - functia reala face scriere Oracle NATIVA (SQLSetprop pe gnHandle, conexiune
|
||||
* SQLCONNECT reala), imposibil de mock-uit prin goExecutor/dummyexecutor (acela intercepteaza
|
||||
* doar apeluri oExecute/oExecuta, nu SQL nativ). Fara mock, testul se opreste la eroarea 1466
|
||||
* "Connection handle is invalid" - asteptata, nu bug (vezi handoff_dvi_discount.md).
|
||||
* Incarcat cu SET PROCEDURE ADDITIVE INAINTE de fisierele reale (castiga primul incarcat,
|
||||
* capcana g - vezi antetul mock_caut_valuta.prg). Foloseste DOAR in test_e2e_dvi_ron_discount.prg,
|
||||
* NU global pentru suita - scrierea reala in ACT/actactan trebuie testata separat, cu conexiune
|
||||
* Oracle vie (nu aici).
|
||||
* Contract: aceiasi parametri ca apelul real (tnScrie_Sterge, tlModificare, tlRul,
|
||||
* tlNuSuprascrieCod, tlLoadBackup - vezi oscrie_in_fisiere.prg:14), intoarce 1 (succes - acelasi
|
||||
* cod folosit de functia reala la finalul ei, linia 108/167).
|
||||
FUNCTION oscrie_in_fisiere
|
||||
LPARAMETERS tnScrie_Sterge, tlModificare, tlRul, tlNuSuprascrieCod, tlLoadBackup
|
||||
IF TYPE('gcUILog') = 'C'
|
||||
DO HarnessLog WITH 'MOCK oscrie_in_fisiere apelat: tnScrie_Sterge=' + TRANSFORM(NVL(tnScrie_Sterge,-1)) + ' tlModificare=' + TRANSFORM(NVL(tlModificare,.F.)) + ' tlRul=' + TRANSFORM(NVL(tlRul,.F.)) + ' -> succes mock'
|
||||
ENDIF
|
||||
RETURN 1
|
||||
ENDFUNC
|
||||
41
utile/Teste/achizitie_import/stub_verificare/verificare.sc2
Normal file
41
utile/Teste/achizitie_import/stub_verificare/verificare.sc2
Normal file
@@ -0,0 +1,41 @@
|
||||
*--------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
* (EN) AUTOGENERATED - ATTENTION!! - NOT INTENDED FOR EXECUTION!! USE ONLY FOR MERGING CHANGES AND STORING WITH SCM TOOLS!!
|
||||
*--------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
*< FOXBIN2PRG: Version="1.21" SourceFile="verificare.scx" CPID="1252" /> (Solo para binarios VFP 9 / Only for VFP 9 binaries)
|
||||
*
|
||||
*
|
||||
DEFINE CLASS dataenvironment AS dataenvironment
|
||||
*< CLASSDATA: Baseclass="dataenvironment" Timestamp="" Scale="" Uniqueid="" ClassIcon="1" />
|
||||
|
||||
*<PropValue>
|
||||
DataSource = .NULL.
|
||||
Height = 0
|
||||
Left = 0
|
||||
Name = "Dataenvironment"
|
||||
Top = 0
|
||||
Width = 0
|
||||
*</PropValue>
|
||||
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS form1 AS form
|
||||
*< CLASSDATA: Baseclass="form" Timestamp="" Scale="" Uniqueid="" />
|
||||
|
||||
*<PropValue>
|
||||
AutoCenter = .T.
|
||||
Caption = "STUB verificare (test harness only)"
|
||||
DoCreate = .T.
|
||||
Height = 100
|
||||
Name = "FORM1"
|
||||
Visible = .F.
|
||||
Width = 200
|
||||
WindowType = 0
|
||||
*</PropValue>
|
||||
|
||||
PROCEDURE Init
|
||||
LPARAMETERS tVerificAnalitic, tAlegPartener, tnButonIntoarcere, tlNuVerificCont
|
||||
gnButon = 1
|
||||
RETURN .F.
|
||||
ENDPROC
|
||||
|
||||
ENDDEFINE
|
||||
@@ -541,8 +541,8 @@ PROCEDURE CreeazaIntrodc
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20))
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE VerificaPereche
|
||||
|
||||
@@ -535,22 +535,21 @@ TRY
|
||||
DO ArLog WITH 'INFO verificare2: cmesajsync gol -> nota SINCRONIZATA'
|
||||
ENDIF
|
||||
|
||||
*-- runda4c (spargere doar factura principala): dupa sincronizeaza(), doar documentul
|
||||
*-- principal (primul B/S din introdc, aici nract=100/RAJA) trebuie spart in randuri S (cont
|
||||
*-- 212); documentele 102 (TRANS OIL MOTO) si 103 (BIROUL VAMAL) trebuie sa ramana B/T
|
||||
*-- neatinse (regula de domeniu: articolele apartin doar facturii principale).
|
||||
LOCAL llDoc100Spart, llDoc102Nesparte, llDoc103Nesparte
|
||||
*-- lSpargeSecundare implicit .T. si documentele 102/103 sunt participante (lIntern=.F.,
|
||||
*-- id_jtva_coloana nenul): dupa sincronizeaza() se sparg TOATE documentele B/S in randuri S
|
||||
*-- pe conturile articolelor (aici doar 212), nu doar documentul principal (100/RAJA).
|
||||
LOCAL llDoc100Spart, llDoc102Spart, llDoc103Spart
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 100 AND tip_rand == 'S'
|
||||
llDoc100Spart = FOUND()
|
||||
LOCATE FOR nract = 102 AND tip_rand == 'B'
|
||||
llDoc102Nesparte = FOUND()
|
||||
LOCATE FOR nract = 103 AND tip_rand == 'B'
|
||||
llDoc103Nesparte = FOUND()
|
||||
IF llDoc100Spart AND llDoc102Nesparte AND llDoc103Nesparte
|
||||
DO ArLog WITH 'PASS verificare3 (runda4c spargere doar principala): doc 100/RAJA spart (rand S gasit), doc 102/103 raman B/T nesparte'
|
||||
LOCATE FOR nract = 102 AND tip_rand == 'S'
|
||||
llDoc102Spart = FOUND()
|
||||
LOCATE FOR nract = 103 AND tip_rand == 'S'
|
||||
llDoc103Spart = FOUND()
|
||||
IF llDoc100Spart AND llDoc102Spart AND llDoc103Spart
|
||||
DO ArLog WITH 'PASS verificare3 (lSpargeSecundare implicit): doc 100/102/103 toate sparte (rand S gasit pe fiecare)'
|
||||
ELSE
|
||||
DO ArLog WITH 'FAIL verificare3 (runda4c spargere doar principala): doc100Spart=' + TRANSFORM(llDoc100Spart) + ' (astept .T.) doc102Nesparte=' + TRANSFORM(llDoc102Nesparte) + ' (astept .T.) doc103Nesparte=' + TRANSFORM(llDoc103Nesparte) + ' (astept .T.)'
|
||||
DO ArLog WITH 'FAIL verificare3 (lSpargeSecundare implicit): doc100Spart=' + TRANSFORM(llDoc100Spart) + ' (astept .T.) doc102Spart=' + TRANSFORM(llDoc102Spart) + ' (astept .T.) doc103Spart=' + TRANSFORM(llDoc103Spart) + ' (astept .T.)'
|
||||
ENDIF
|
||||
|
||||
*========================= PAS 2: dupa sincronizeaza() =========================
|
||||
@@ -691,8 +690,8 @@ PROCEDURE CreeazaIntrodc
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20))
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE VerificaPereche
|
||||
|
||||
@@ -254,7 +254,7 @@ TRY
|
||||
|
||||
*-- index ord_doc INAINTE de CREATEOBJECT - vezi docs/testare-ui-vfp.md capcana p.
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='T','3', tip_rand='D','4', '5') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO ApLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F.) - lIntern=.F. (import)'
|
||||
@@ -566,8 +566,8 @@ PROCEDURE CreeazaIntrodc
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20))
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DumpIntrodc
|
||||
|
||||
@@ -281,8 +281,8 @@ poAct.AddProperty('id_valuta', 1)
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20))
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
|
||||
INSERT INTO introdc (tip_rand, scd, scc, ascc, suma, suma_val, id_jtva_coloana, ptva, explicatie_tva, ;
|
||||
in_valuta, participa_valuta, id_valuta, curs, nume_val, nr_doc, nract, serie_act, fdoc, partc, explicatia, ;
|
||||
|
||||
@@ -0,0 +1,670 @@
|
||||
* test_diag_controlsource_calificat.prg
|
||||
* REGRESIE (initial diagnostic - a demonstrat un ocolire a gardei, acum fixata): izoleaza
|
||||
* copiaza_valoare() de dialog/sparge_document, insert direct in introdc - doua randuri,
|
||||
* acelasi doc_key: B nract=15000/id_fdoc=1/id_partc=601, T-DVI nract=101/id_fdoc=2/
|
||||
* id_partc=900/rand_dvi=1.
|
||||
*
|
||||
* Context: This.Parent.ControlSource (folosit de Grid1.cNract/cDataAct/cSerie_act.Text1.Valid
|
||||
* ca argument pentru Thisform.copiaza_valoare) e "nract" la design-time in .vcx, dar la
|
||||
* runtime VFP il rescrie calificat cu alias-ul RecordSource-ului grid-ului ("introdc.nract").
|
||||
* Garda din copiaza_valoare (COMUN\clase\ointroduceri.vcx) normalizeaza acum tcCamp la numele
|
||||
* de camp BAR (dupa ultimul punct) inainte de Inlist - testul verifica DIRECT ca garda
|
||||
* blocheaza propagarea de pe randul T-DVI (sursa) atat pe drumul real (Grid1.cNract/
|
||||
* cDataAct.Text1.Valid()), cat si prin apel direct cu literalul 'nract'. Grid1.cPartC.
|
||||
* Text1.Valid NU foloseste copiaza_valoare (are logica proprie, verificari directe pe
|
||||
* rand_dvi) - neafectat de aceasta problema, testat separat in test_repro_trigger_partener.prg.
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_diag_controlsource_calificat.ps1
|
||||
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_diag_controlsource_calificat_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_diag_controlsource_calificat\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO EeErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'COMUN\Utile\Teste\achizitie_import\stub_verificare;' + ;
|
||||
gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO EeLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO EeLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_cauta_nom_articole.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_oscrie_in_fisiere.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO EeLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnMockRaspuns, gcMockUltimMesaj, gnMockUltimTip, gcMockArtCodmat
|
||||
gnMockRaspuns = 6
|
||||
gcMockUltimMesaj = ''
|
||||
gnMockUltimTip = 0
|
||||
PUBLIC gnButon
|
||||
gnButon = 1
|
||||
gcMockArtCodmat = ''
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (factura import EUR, curs 5.23) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 5.23)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 601)
|
||||
poAct.AddProperty('partc', 'FURNIZOR EXTERN GMBH')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: perechi reale 21% (achizitii interne + import) -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 208, 'ACH. INT. 21%', 1, 0, 1, 'RO21B', 'RO21T', 21, 209)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 209, 'TVA ACH. INT. 21%', 1, 0, 1, 'RO21T', '', 21, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (3, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (4, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 208, 21, 'ACH. INT. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 209, 21, 'TVA ACH. INT. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
DO CreeazaRulTemp
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
*-- index ord_doc INAINTE de CREATEOBJECT (capcana p, docs/testare-ui-vfp.md)
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
*-- vezi antetul test_e2e_dvi_ron_discount.prg: tlIntern BARA, aceeasi valoare ca la CREATEOBJECT
|
||||
PRIVATE tlIntern
|
||||
tlIntern = .F.
|
||||
|
||||
PUBLIC gcTempPath
|
||||
gcTempPath = ADDBS(SYS(2023))
|
||||
PUBLIC gnHandle
|
||||
gnHandle = -1
|
||||
PUBLIC gnTipGest
|
||||
gnTipGest = 0
|
||||
PUBLIC gcCondSucursala
|
||||
gcCondSucursala = ''
|
||||
|
||||
DO EeLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F. - mod import)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO EeLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
DO HarnessStep WITH 0, 'nota goala afisata, mod import (.F.)'
|
||||
|
||||
*========================= DIAGNOSTIC: insert DIRECT (fara dialog), izoleaza copiaza_valoare() =========================
|
||||
*-- doua randuri, ACELASI doc_key: B (nract=15000/id_fdoc=1/id_partc=601) si T-DVI
|
||||
*-- (nract=101/id_fdoc=2/id_partc=900, rand_dvi=1) - minim necesar ca sa testam DOAR garda
|
||||
*-- din copiaza_valoare(), fara sparge_document/sincronizare/dialog in cale.
|
||||
SELECT introdc
|
||||
APPEND BLANK
|
||||
REPLACE nract WITH 15000, id_fdoc WITH 1, id_partc WITH 601, serie_act WITH '', ;
|
||||
tip_rand WITH 'B', nr_doc WITH 1, scd WITH '371', scc WITH '401', suma WITH 5000, ;
|
||||
rand_dvi WITH 0, dataact WITH {^2026-07-20}
|
||||
APPEND BLANK
|
||||
REPLACE nract WITH 101, id_fdoc WITH 2, id_partc WITH 900, serie_act WITH '', ;
|
||||
tip_rand WITH 'T', nr_doc WITH 1, scd WITH '4426', scc WITH '401', suma WITH 900, ;
|
||||
rand_dvi WITH 1, dataact WITH {^2026-07-25}
|
||||
*-- doc_key IDENTIC pe ambele randuri (T-DVI pastreaza doc_key-ul MAMEI, calculat pe baza
|
||||
*-- identitatii facturii B - la fel ca in do_adauga_factura, unde Replace doc_key se face
|
||||
*-- INAINTE de suprascrierea cu identitatea vamala pe randul T)
|
||||
LOCAL lcDocKeyComun
|
||||
SELECT introdc
|
||||
GO TOP
|
||||
lcDocKeyComun = goObj.calc_doc_key()
|
||||
REPLACE ALL doc_key WITH lcDocKeyComun
|
||||
GO TOP
|
||||
|
||||
DO DumpIntrodc WITH 'DUMP inainte de copiaza_valoare (insert direct, fara dialog)'
|
||||
|
||||
DO HarnessStep WITH 1, 'randuri B/T-DVI inserate direct, acelasi doc_key'
|
||||
|
||||
*========================= TRIGGER: pointerul pe randul T-DVI, copiaza_valoare('nract') DIRECT =========================
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('17-pozitionare pe randul T-DVI reusita (inainte de trigger)', IIF(FOUND(),1,0), 1)
|
||||
|
||||
LOCAL llTriggerOk
|
||||
llTriggerOk = .F.
|
||||
IF FOUND()
|
||||
DO EeLog WITH 'DEBUG Grid1.cNract.ControlSource=[' + goObj.Grid1.cNract.ControlSource + '] LEN=' + TRANSFORM(LEN(goObj.Grid1.cNract.ControlSource)) + ' vs literal [nract] LEN=' + TRANSFORM(LEN('nract'))
|
||||
DO EeLog WITH 'DEBUG Grid1.cDataAct.ControlSource=[' + goObj.Grid1.cDataAct.ControlSource + '] LEN=' + TRANSFORM(LEN(goObj.Grid1.cDataAct.ControlSource))
|
||||
DO EeLog WITH 'DEBUG Grid1.cSerie_act.ControlSource=[' + goObj.Grid1.cSerie_act.ControlSource + '] LEN=' + TRANSFORM(LEN(goObj.Grid1.cSerie_act.ControlSource))
|
||||
goObj.Grid1.cNract.Text1.Valid()
|
||||
llTriggerOk = .T.
|
||||
ENDIF
|
||||
DOEVENTS FORCE
|
||||
=Assert3('18-TRIGGER executat fara eroare', IIF(llTriggerOk,1,0), 1)
|
||||
DO EeLog WITH 'TRIGGER folosit: Grid1.cNract.Text1.Valid()'
|
||||
|
||||
DO DumpIntrodc WITH 'DUMP dupa TRIGGER (copiaza_valoare direct, pointer pe T-DVI)'
|
||||
|
||||
*========================= TRIGGER 2: acelasi izolat, dar pe coloana Data (cDataAct) =========================
|
||||
*-- randul B primeste si el o data (diferita de T-DVI), ca sa se poata verifica propagarea
|
||||
SELECT introdc
|
||||
GO 1
|
||||
REPLACE dataact WITH {^2026-07-20}
|
||||
GO 2
|
||||
REPLACE dataact WITH {^2026-07-25}
|
||||
GO 2
|
||||
|
||||
LOCAL llTrigger2Ok
|
||||
llTrigger2Ok = .F.
|
||||
goObj.Grid1.cDataAct.Text1.Valid()
|
||||
llTrigger2Ok = .T.
|
||||
DOEVENTS FORCE
|
||||
=Assert3('19-TRIGGER 2 (cDataAct) executat fara eroare', IIF(llTrigger2Ok,1,0), 1)
|
||||
|
||||
DO DumpIntrodc WITH 'DUMP dupa TRIGGER 2 (cDataAct.Valid, pointer pe T-DVI)'
|
||||
|
||||
GO 1 IN introdc
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF introdc.dataact == {^2026-07-20}
|
||||
pnPass = pnPass + 1
|
||||
DO EeLog WITH ' PASS 20-randul B (dataact) NESCHIMBAT dupa TRIGGER 2 (=' + DTOC(introdc.dataact) + ')'
|
||||
ELSE
|
||||
DO EeLog WITH ' FAIL 20-randul B (dataact) a devenit ' + DTOC(introdc.dataact) + ' dupa TRIGGER 2 (asteptat 20.07.2026)'
|
||||
ENDIF
|
||||
|
||||
*========================= ASSERT-URI DUPA TRIGGER: nract pe B trebuie sa RAMANA 15000 =========================
|
||||
LOCAL llBugG, llBugS, lnCntSVerif
|
||||
llBugG = .F.
|
||||
llBugS = .F.
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR tip_rand == 'B' AND Nvl(rand_dvi,0) <> 1
|
||||
IF FOUND()
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF nract == 15000
|
||||
pnPass = pnPass + 1
|
||||
DO EeLog WITH ' PASS 20-B.nract ramane 15000 dupa trigger (=' + TRANSFORM(nract) + ')'
|
||||
ELSE
|
||||
llBugG = .T.
|
||||
DO EeLog WITH ' FAIL 20-B.nract dupa trigger = ' + TRANSFORM(nract) + ' (asteptat 15000) -> BUG'
|
||||
ENDIF
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO EeLog WITH ' FAIL 20: randul B negasit dupa trigger'
|
||||
ENDIF
|
||||
|
||||
*-- randul T-DVI insusi trebuie sa ramana 101 (sursa neschimbata de propriul apel)
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('22-T-DVI.nract ramane 101 (randul sursa neschimbat)', IIF(FOUND(), nract, -1), 101)
|
||||
|
||||
*-- doc_key: NU trebuie regenerat (llSursaProtejata blocheaza si regenerarea de doc_key)
|
||||
LOCAL lcDocKeyB, lcDocKeyT
|
||||
SELECT introdc
|
||||
LOCATE FOR tip_rand == 'B'
|
||||
lcDocKeyB = ALLTRIM(NVL(doc_key,''))
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
lcDocKeyT = ALLTRIM(NVL(doc_key,''))
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF lcDocKeyB == lcDocKeyT
|
||||
pnPass = pnPass + 1
|
||||
DO EeLog WITH ' PASS 25-doc_key B si T-DVI raman identice dupa trigger ([' + lcDocKeyB + '])'
|
||||
ELSE
|
||||
DO EeLog WITH ' FAIL 25-doc_key B=[' + lcDocKeyB + '] <> doc_key T-DVI=[' + lcDocKeyT + '] dupa trigger'
|
||||
ENDIF
|
||||
|
||||
LOCAL llBugSDupaSync2
|
||||
llBugSDupaSync2 = .F.
|
||||
|
||||
DO HarnessStep WITH 2, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
|
||||
DO EeLog WITH '========================================================='
|
||||
IF llBugG OR llBugS OR llBugSDupaSync2
|
||||
DO EeLog WITH 'BUG CONFIRMAT: nract-ul randului T-DVI (101) s-a propagat peste nract-ul' + ;
|
||||
' randurilor B/G/S ale facturii principale (asteptat 15000) dupa ce Valid()/' + ;
|
||||
'copiaza_valoare() a rulat cu pointerul pe randul T-DVI.'
|
||||
ELSE
|
||||
DO EeLog WITH 'BUG NECONFIRMAT: nract-ul randurilor B/G/S a ramas 15000 dupa trigger si dupa re-sincronizare.'
|
||||
ENDIF
|
||||
DO EeLog WITH '========================================================='
|
||||
|
||||
DO EeLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO EeLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO EeLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO EeLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE DumpIntrodc
|
||||
LPARAMETERS tcTitlu
|
||||
LOCAL lcSelAnt, lnRecAnt
|
||||
lcSelAnt = SELECT()
|
||||
lnRecAnt = IIF(USED('introdc'), IIF(EOF('introdc') OR BOF('introdc'), 0, RECNO('introdc')), 0)
|
||||
DO EeLog WITH tcTitlu
|
||||
IF !USED('introdc')
|
||||
DO EeLog WITH ' (introdc neinstantiat)'
|
||||
RETURN
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
SCAN
|
||||
DO EeLog WITH ' tip_rand=' + ALLTRIM(NVL(tip_rand,'?')) + ' nract=' + TRANSFORM(NVL(nract,0)) + ;
|
||||
' doc_key=[' + ALLTRIM(NVL(doc_key,'')) + '] rand_dvi=' + TRANSFORM(NVL(rand_dvi,0)) + ;
|
||||
' scd=' + ALLTRIM(NVL(scd,'')) + ' scc=' + ALLTRIM(NVL(scc,'')) + ' suma=' + TRANSFORM(NVL(suma,0))
|
||||
ENDSCAN
|
||||
IF lnRecAnt > 0
|
||||
TRY
|
||||
GO lnRecAnt
|
||||
CATCH
|
||||
GO TOP
|
||||
ENDTRY
|
||||
ENDIF
|
||||
SELECT (lcSelAnt)
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaIntrodc
|
||||
*-- coloane rand_dvi N(1), valuta_proprie N(1) (rand_dvi = randul T-DVI)
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaRulTemp
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp ( ;
|
||||
id_rul N(20,0), an N(4,0), luna N(2,0), cod N(20,0);
|
||||
, serie C(100), nnir N(20,0), id_articol N(10,0), denumire C(100);
|
||||
, codmat C(50), codmatf C(50), codbare C(50), um C(20);
|
||||
, id_gestiune N(5,0), nume_gestiune C(50), cgest C(20), nr_pag N(2,0);
|
||||
, gestionar C(50), comisie_receptie1 C(50), comisie_receptie2 C(50), comisie_receptie3 C(50);
|
||||
, cant N(14,3), cante N(14,3), cont C(10), acont C(20);
|
||||
, pret N(18,4), tva N(18,4), valoare N(18,4), valtva N(18,4);
|
||||
, proc_tva N(5,2), pretv N(18,4), pretvtva N(18,4), tvav N(18,4);
|
||||
, valoarev N(18,4), valtvav N(18,4), proc_tvav N(5,2), adaos N(18,4);
|
||||
, adaos_tva N(18,4), valoare_adaos N(18,4), valtva_adaos N(18,4), procent N(10,3);
|
||||
, discunitar N(18,4), discount_tva N(18,4), valoare_discount N(18,4), valtva_discount N(18,4);
|
||||
, proc_disc N(7,3), pretd N(14,4), curs N(18,4), id_valuta N(10,0);
|
||||
, nume_val C(20), id_lucrare N(20,0), nrord C(100), id_responsabil N(10,0);
|
||||
, nresp C(100), resp_marca N(18,4), dataact T, id_util N(5,0);
|
||||
, util C(30), dataora T, id_sectie N(5,0), sectie C(50);
|
||||
, csectie C(10), alcooltutun N(1,0), datain T, dataout T;
|
||||
, id_fact N(20,0), id_gestiunec N(10,0), nume_gestiunec C(50), cgestc C(20);
|
||||
, id_responsabilc N(5,0), id_reteta N(10,0), reteta C(50), nrespc C(100);
|
||||
, respc_marca N(18,4), id_set N(20,0), id_tip_rulaj N(10,0), tip_rulaj C(50);
|
||||
, id_obiect_depozit N(10,0), id_rul_aux N(10,0), nract N(20,0), serie_act C(10);
|
||||
, dataoras T, id_utils N(10,0), lot C(30), adata_expirare T;
|
||||
, id_sucursala N(5,0), sucursala C(250), id_part_rez N(10,0), part_rez C(100);
|
||||
, id_lucrare_rez N(10,0), nrord_rez C(100), subgrupa C(100), grupa C(100);
|
||||
, id_subgrupa N(5,0), id_grupa N(5,0), in_stoc N(1,0), in_crm N(1,0);
|
||||
, id_furnizor N(10,0), furnizor C(100), id_jtva_coloana N(4,0), explicatie_tva C(100);
|
||||
, taxcode N(6,0), taxname C(254), saft_procent N(18,4), codnc8 C(20);
|
||||
, id_tara_origine N(4,0), cod_tara_origine C(5), tara_origine C(50), greutate N(12,4);
|
||||
, fdoc C(30), id_fdoc N(18,4);
|
||||
, pret_lei N(18,4), pret_val N(14,4), cota_tva N(6,2))
|
||||
ENDPROC
|
||||
|
||||
FUNCTION RECCOUNT_ACTIVE
|
||||
LPARAMETERS tcAlias
|
||||
LOCAL lnSel, lnCnt
|
||||
lnSel = SELECT()
|
||||
SELECT (tcAlias)
|
||||
COUNT TO lnCnt FOR !DELETED()
|
||||
SELECT (lnSel)
|
||||
RETURN lnCnt
|
||||
ENDFUNC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO EeLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO EeLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE AssertStr
|
||||
LPARAMETERS tcLabel, tcActual, tcExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF tcActual == tcExpected
|
||||
pnPass = pnPass + 1
|
||||
DO EeLog WITH ' PASS ' + tcLabel + ' (=[' + tcActual + '])'
|
||||
ELSE
|
||||
DO EeLog WITH ' FAIL ' + tcLabel + ' (actual=[' + tcActual + '] asteptat=[' + tcExpected + '])'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE EeErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO EeLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE EeLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES (IIF(TYPE('gcMockAcontCrt') = 'C', gcMockAcontCrt, ''))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VCONFIG_CONT_IREG' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (contpart C(10), fel_cont N(1), cu_inregistrari N(1), ;
|
||||
explic_cont C(100), exceptie C(10), pozitie N(1), invers N(1), gasit N(1))
|
||||
INSERT INTO (m.tcCursor) VALUES ('401', 0, 0, 'Furnizori', '', 0, 0, 0)
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (208, 'ACH. INT. 21%', 1, 0, 'RO21B', 21, 209, 1, 1, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (209, 'TVA ACH. INT. 21%', 1, 0, 'RO21T', 21, 1, 2, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 3, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 4, 301204)
|
||||
ENDPROC
|
||||
@@ -0,0 +1,15 @@
|
||||
# test_diag_controlsource_calificat.ps1 - DIAGNOSTIC: izoleaza copiaza_valoare() de dialog/
|
||||
# sparge_document, ca sa demonstreze ca garda noua (rand-sursa protejat, adaugata in fix)
|
||||
# functioneaza CORECT cand tcCamp e literalul 'nract', dar e OCOLITA cand tcCamp vine din
|
||||
# This.Parent.ControlSource al coloanei Grid1.cNract, pentru ca la runtime ControlSource
|
||||
# devine "introdc.nract" (calificat cu alias-ul), nu "nract" (asa cum apare la design-time
|
||||
# in .vcx) - vezi test_diag_controlsource_calificat_log.txt.
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Teste = $PSScriptRoot
|
||||
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
|
||||
-TestPrg (Join-Path $Teste 'test_diag_controlsource_calificat.prg') `
|
||||
-Steps @('nota_goala','randuri_inserate','final') `
|
||||
-ShotsDir (Join-Path $Teste 'screenshots_diag_controlsource_calificat') `
|
||||
-SyncDir (Join-Path $Teste 'uisync_diag_controlsource_calificat') `
|
||||
-StepTimeoutSec 180 `
|
||||
-ReadyTimeoutSec 180
|
||||
878
utile/Teste/achizitie_import/test_discount_factura.prg
Normal file
878
utile/Teste/achizitie_import/test_discount_factura.prg
Normal file
@@ -0,0 +1,878 @@
|
||||
* test_discount_factura.prg
|
||||
* Runda32 (model B/G/T, plan docs/plan_runda32_discount_baza.md): discount financiar pe factura
|
||||
* de import - UN SINGUR rand nou tip_rand='G' (acelasi doc_key/nr_doc cu factura), creat intre
|
||||
* randul B si randul T:
|
||||
* G: scd = contul 401 (cu analitic) preluat de pe CREDITUL randului B, scc='767', suma/
|
||||
* suma_val = baza discount (POZITIVE), id_partd/partd = partenerul facturii (preluat de
|
||||
* pe creditul B), participa_valuta=.F., cota/coloana de TVA ale bazei documentului,
|
||||
* explicatia='DISCOUNT'.
|
||||
* Randul T (4426/4427) se calculeaza pe baza NETA: T.suma = (B.suma - G.suma) * ptva/100,
|
||||
* T.suma_val = (B.suma_val - G.suma_val) * ptva/100 - calculat automat de do_executa() (apelat
|
||||
* din do_adauga_factura), nu necesita pas separat.
|
||||
* Verifica: conturi/sume/semne/parteneri corecte pe G; ordinea fizica in cursor (Append Blank:
|
||||
* B -> G -> T); T calculat pe baza neta; preturile articolelor si randul D neafectate; G
|
||||
* supravietuieste sparge_document/uneste_document/sincronizeaza (nu doar la creare); stergere
|
||||
* factura (document) sterge si discountul; variante discount=0 (fara G) si factura in RON
|
||||
* (fara valuta).
|
||||
*
|
||||
* ASUMPTII (de confruntat cu implementarea reala):
|
||||
* - toDlg poarta disc_baza_lei/disc_baza_val (fara are_discount/disc_tva_lei/disc_tva_val,
|
||||
* eliminate in Runda32); discountul e activ cand Round(Nvl(toDlg.disc_baza_lei,0),gnPC)<>0;
|
||||
* - G se scrie DUPA Endcase-ul ramurii de TVA (F/D/N), inainte de crearea randului T (plan
|
||||
* pct. 6: ordinea devine B -> G -> T), clonat din randul B proaspat creat;
|
||||
* - assert-ul pe actactan/inainte_de_do_termin (:9555 zona, !Inlist(tip_rand,'D','G')) e
|
||||
* best-effort (TRY/CATCH) - harness-ul nu modeleaza integral scrierea reala in ACT/actactan;
|
||||
* - grid-ul NU are index de sortare in productie (randurile noi se adauga la finalul
|
||||
* cursorului) - verificarea de ordine se face pe RECNO fizic, imediat dupa creare, nu pe un
|
||||
* index custom.
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_discount_factura.ps1
|
||||
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_discount_factura_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_discount_factura\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO DcErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO DcLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO DcLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_cauta_nom_articole.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO DcLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
PUBLIC goMockValuta
|
||||
goMockValuta = CREATEOBJECT('Custom')
|
||||
goMockValuta.AddProperty('id_valuta', 978)
|
||||
goMockValuta.AddProperty('nume_val', 'EUR')
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnButon
|
||||
STORE 2 TO gnButon
|
||||
PUBLIC gcMockArtCodmat, gcMockAcontCrt
|
||||
gcMockArtCodmat = ''
|
||||
gcMockAcontCrt = ''
|
||||
PUBLIC gnMockRaspuns
|
||||
gnMockRaspuns = 6
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (moneda principala EUR, curs 5.23) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 5.23)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 601)
|
||||
poAct.AddProperty('partc', 'RAJA')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: perechi reale 21% -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 208, 'ACH. INT. 21%', 1, 0, 1, 'RO21B', 'RO21T', 21, 209)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 209, 'TVA ACH. INT. 21%', 1, 0, 1, 'RO21T', '', 21, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (3, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (4, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 208, 21, 'ACH. INT. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 209, 21, 'TVA ACH. INT. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
DO CreeazaRulTemp
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO DcLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F.)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO DcLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
*========================= DOC1: FACTURA EUR + discount (100 EUR / 523.00 lei, curs 5.23) =========================
|
||||
PUBLIC goDlg, goT, gcDocKey1, gnB1ScdCredit, gnB1IdPartc, gcB1Partc
|
||||
DO AdaugaFactura WITH 15000, 'RAJA', 601, 100.00
|
||||
DO HarnessStep WITH 0, 'dupa DOC1 (cu discount): introdc=' + TRANSFORM(RECCOUNT_ACTIVE('introdc')) + ' randuri'
|
||||
|
||||
SELECT introdc
|
||||
SET ORDER TO
|
||||
LOCATE FOR nract = 15000 AND tip_rand == 'B'
|
||||
=Assert3('1-DOC1: rand B gasit', IIF(FOUND(),1,0), 1)
|
||||
LOCAL lnRecnoB1
|
||||
lnRecnoB1 = 0
|
||||
IF FOUND()
|
||||
gcDocKey1 = ALLTRIM(NVL(doc_key,''))
|
||||
gnB1IdPartc = id_partc
|
||||
gcB1Partc = ALLTRIM(NVL(partc,''))
|
||||
lnRecnoB1 = RECNO()
|
||||
ENDIF
|
||||
|
||||
LOCAL lnCntG1, lnRecnoG1, lnRecnoT1
|
||||
STORE 0 TO lnCntG1, lnRecnoG1, lnRecnoT1
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1
|
||||
DO CASE
|
||||
CASE tip_rand == 'G'
|
||||
lnCntG1 = lnCntG1 + 1
|
||||
lnRecnoG1 = RECNO()
|
||||
DO DcLog WITH 'DOC1 G: scd=' + ALLTRIM(scd) + ' scc=' + ALLTRIM(scc) + ' suma=' + TRANSFORM(suma) + ' suma_val=' + TRANSFORM(suma_val) + ' id_partd=' + TRANSFORM(NVL(id_partd,0)) + ' explicatia=[' + ALLTRIM(NVL(explicatia,'')) + ']'
|
||||
CASE tip_rand == 'T' AND lnRecnoT1 = 0
|
||||
lnRecnoT1 = RECNO()
|
||||
ENDCASE
|
||||
ENDSCAN
|
||||
=Assert3('2-DOC1: exact 1 rand G (model B/G/T)', lnCntG1, 1)
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'G'
|
||||
=Assert3('3-DOC1: randul G gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=AssertStr('4-G.scd == 401 (analitic preluat de pe creditul B)', ALLTRIM(scd), '401')
|
||||
=AssertStr('5-G.scc == 767', ALLTRIM(scc), '767')
|
||||
=Assert3('6-G.suma=523.00 (POZITIVA, 100 EUR x curs 5.23)', suma, 523.00)
|
||||
=Assert3('7-G.suma_val=100.00 (POZITIVA)', suma_val, 100.00)
|
||||
=Assert3('8-G.id_partd = partenerul facturii (preluat de pe creditul B)', NVL(id_partd,0), gnB1IdPartc)
|
||||
=AssertStr('9-G.partd = partenerul facturii', ALLTRIM(NVL(partd,'?')), gcB1Partc)
|
||||
=Assert3('10-G.participa_valuta=.F.', IIF(participa_valuta,1,0), 0)
|
||||
=Assert3('11-G.ptva = cota documentului (G e baza de TVA)', NVL(ptva,0), 21)
|
||||
=Assert3('12-G.cu_tva=1', NVL(cu_tva,0), 1)
|
||||
=Assert3('13-G.id_jtva_coloana = coloana bazei', NVL(id_jtva_coloana,0), goDlg.nIdExplicatieTva)
|
||||
=AssertStr('14-G.explicatia=DISCOUNT', ALLTRIM(NVL(explicatia,'?')), 'DISCOUNT')
|
||||
=AssertStr('15-G.doc_key = doc_key facturii', ALLTRIM(NVL(doc_key,'?')), gcDocKey1)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 11
|
||||
DO DcLog WITH ' FAIL 4-15: G negasit'
|
||||
ENDIF
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'T'
|
||||
=Assert3('16-DOC1: randul T gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('17-T.suma=988.47 ((5230.00-523.00)*21%, baza NETA)', suma, 988.47)
|
||||
=Assert3('18-T.suma_val=189.00 ((1000.00-100.00)*21%, baza NETA in valuta)', suma_val, 189.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DcLog WITH ' FAIL 17-18: T negasit'
|
||||
ENDIF
|
||||
|
||||
*========================= ORDINE FIZICA IN CURSOR (Append Blank: B -> G -> T) =========================
|
||||
=Assert3('19-ordine fizica: B/G/T gasite (recno>0)', IIF(lnRecnoB1>0 AND lnRecnoG1>0 AND lnRecnoT1>0,1,0), 1)
|
||||
=Assert3('20-ordine fizica: RECNO(B) < RECNO(G)', IIF(lnRecnoB1 < lnRecnoG1,1,0), 1)
|
||||
=Assert3('21-ordine fizica: RECNO(G) < RECNO(T)', IIF(lnRecnoG1 < lnRecnoT1,1,0), 1)
|
||||
|
||||
DO HarnessStep WITH 1, 'DOC1 (G creat, T pe baza neta) verificat - vezi log'
|
||||
|
||||
*========================= ARTICOL + PRETURI NEAFECTATE DE DISCOUNT =========================
|
||||
SELECT introdc
|
||||
SET ORDER TO ord_doc
|
||||
gcMockArtCodmat = 'ART-BULD-212'
|
||||
gcMockAcontCrt = '1'
|
||||
TRY
|
||||
goObj.do_adauga_articol()
|
||||
CATCH TO loExcA1
|
||||
DO DcLog WITH 'EROARE do_adauga_articol ' + TRANSFORM(loExcA1.ErrorNo) + ' [' + loExcA1.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-BULD-212'
|
||||
IF FOUND()
|
||||
REPLACE cant WITH 1, pret_val WITH 1000, pretd WITH 1000, pret WITH ROUND(1000*5.23,4), pret_lei WITH ROUND(1000*5.23,4)
|
||||
ENDIF
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
LOCAL llEroareSync1
|
||||
llEroareSync1 = .F.
|
||||
TRY
|
||||
goObj.sincronizeaza()
|
||||
CATCH TO loExcS1
|
||||
llEroareSync1 = .T.
|
||||
DO DcLog WITH 'EROARE la sincronizeaza() ' + TRANSFORM(loExcS1.ErrorNo) + ' [' + loExcS1.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
=Assert3('22-sincronizeaza() (dupa articol) fara eroare', IIF(llEroareSync1,0,1), 1)
|
||||
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-BULD-212'
|
||||
IF FOUND()
|
||||
=Assert3('23-pretul articolului NEAFECTAT de discount (pretd=1000)', pretd, 1000)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO DcLog WITH ' FAIL 23: articolul negasit dupa sincronizare'
|
||||
ENDIF
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR tip_rand == 'D'
|
||||
IF FOUND()
|
||||
DO DcLog WITH 'rand D (diferenta) dupa discount+articol: suma=' + TRANSFORM(suma)
|
||||
=Assert3('24-randul D NEAFECTAT de discount (|suma|<=0.02)', ABS(suma), 0)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
pnPass = pnPass + 1
|
||||
DO DcLog WITH ' INFO 24: nu exista rand D (diferenta 0) - OK'
|
||||
ENDIF
|
||||
|
||||
*========================= G SUPRAVIETUIESTE dupa sincronizare (nu doar la creare) =========================
|
||||
LOCAL lnCntGDupaSync
|
||||
lnCntGDupaSync = 0
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'G'
|
||||
lnCntGDupaSync = lnCntGDupaSync + 1
|
||||
ENDSCAN
|
||||
=Assert3('25-dupa sincronizare (cu articol): tot 1 rand G (nu s-a dublat/sters)', lnCntGDupaSync, 1)
|
||||
|
||||
*-- a doua sincronizare (stabilitate la re-rulare)
|
||||
TRY
|
||||
goObj.sincronizeaza()
|
||||
CATCH TO loExcS2
|
||||
DO DcLog WITH 'EROARE la sincronizeaza() #2 ' + TRANSFORM(loExcS2.ErrorNo) + ' [' + loExcS2.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
LOCAL lnCntGDupaSync2
|
||||
lnCntGDupaSync2 = 0
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'G'
|
||||
lnCntGDupaSync2 = lnCntGDupaSync2 + 1
|
||||
ENDSCAN
|
||||
=Assert3('26-dupa a doua sincronizare: tot 1 rand G (stabil)', lnCntGDupaSync2, 1)
|
||||
|
||||
DO HarnessStep WITH 2, 'articol/preturi/stabilitate G verificate - vezi log'
|
||||
|
||||
*========================= inainte_de_do_termin: G nu genereaza rand fals de finalizare NIR (best-effort) =========================
|
||||
TRY
|
||||
goObj.inainte_de_do_termin()
|
||||
DO DcLog WITH 'INFO inainte_de_do_termin() rulat fara eroare'
|
||||
IF USED('actactan')
|
||||
LOCAL lnCntGActactan
|
||||
lnCntGActactan = 0
|
||||
SELECT actactan
|
||||
SCAN FOR tip_rand == 'G'
|
||||
lnCntGActactan = lnCntGActactan + 1
|
||||
ENDSCAN
|
||||
DO DcLog WITH 'actactan: ' + TRANSFORM(lnCntGActactan) + ' randuri G gasite (fara relevanta pt NIR fals - vezi INFO)'
|
||||
ELSE
|
||||
DO DcLog WITH 'INFO: cursorul actactan nu exista in acest harness (scriere reala neacoperita de dummyexecutor) - assert 27 omis'
|
||||
ENDIF
|
||||
CATCH TO loExcNir
|
||||
DO DcLog WITH 'INFO inainte_de_do_termin() a aruncat eroare in acest harness (dependent de Oracle real): ' + loExcNir.Message + ' - assert 27 omis'
|
||||
ENDTRY
|
||||
|
||||
DO HarnessStep WITH 3, 'inainte_de_do_termin (best-effort) verificat - vezi log'
|
||||
|
||||
*========================= STERGERE FACTURA -> STERGE SI DISCOUNTUL =========================
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'B'
|
||||
IF !FOUND()
|
||||
*-- dupa spargere B poate lipsi - folosesc orice rand al documentului pentru pozitionare
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1
|
||||
ENDIF
|
||||
=Assert3('28-rand al DOC1 gasit pentru stergere', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
gnMockRaspuns = 6 && Da = tot documentul
|
||||
TRY
|
||||
goObj.do_sterge()
|
||||
CATCH TO loExcDel
|
||||
DO DcLog WITH 'EROARE do_sterge ' + TRANSFORM(loExcDel.ErrorNo) + ' [' + loExcDel.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
ENDIF
|
||||
LOCAL lnCntDupaStergere
|
||||
lnCntDupaStergere = 0
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1
|
||||
lnCntDupaStergere = lnCntDupaStergere + 1
|
||||
ENDSCAN
|
||||
=Assert3('29-dupa stergere document: 0 randuri ramase (inclusiv G)', lnCntDupaStergere, 0)
|
||||
|
||||
DO HarnessStep WITH 4, 'stergere factura + discount verificata - vezi log'
|
||||
|
||||
*========================= VARIANTA A: discount = 0 (fara G, T pe baza integrala) =========================
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
PUBLIC gcDocKey2
|
||||
DO AdaugaFactura WITH 15001, 'TRANS OIL', 602, 0.00
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 15001 AND tip_rand == 'B'
|
||||
IF FOUND()
|
||||
gcDocKey2 = ALLTRIM(NVL(doc_key,''))
|
||||
ENDIF
|
||||
LOCAL lnCntG2A
|
||||
lnCntG2A = 0
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey2 AND tip_rand == 'G'
|
||||
lnCntG2A = lnCntG2A + 1
|
||||
ENDSCAN
|
||||
=Assert3('30-VARIANTA discount=0: niciun rand G', lnCntG2A, 0)
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey2 AND tip_rand == 'T'
|
||||
=Assert3('31-VARIANTA discount=0: randul T gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('32-VARIANTA discount=0: T.suma=1098.30 (baza integrala 5230.00*21%)', suma, 1098.30)
|
||||
=Assert3('33-VARIANTA discount=0: T.suma_val=210.00 (baza integrala 1000.00*21%)', suma_val, 210.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DcLog WITH ' FAIL 32-33: T (discount=0) negasit'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 5, 'varianta discount=0 verificata - vezi log'
|
||||
|
||||
*========================= VARIANTA B: FACTURA IN RON (fara valuta) + discount 400 lei =========================
|
||||
PUBLIC gcDocKey3
|
||||
DO AdaugaFacturaRon WITH 15002, 'FURNIZOR INTERN SRL', 603, 400.00
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 15002 AND tip_rand == 'B'
|
||||
IF FOUND()
|
||||
gcDocKey3 = ALLTRIM(NVL(doc_key,''))
|
||||
ENDIF
|
||||
LOCAL lnCntG3
|
||||
lnCntG3 = 0
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey3 AND tip_rand == 'G'
|
||||
lnCntG3 = lnCntG3 + 1
|
||||
=Assert3('34.'+TRANSFORM(RECNO())+'-VARIANTA RON: G.suma_val=0 (fara valuta)', NVL(suma_val,0), 0)
|
||||
ENDSCAN
|
||||
=Assert3('35-VARIANTA RON: exact 1 rand G', lnCntG3, 1)
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey3 AND tip_rand == 'G'
|
||||
IF FOUND()
|
||||
=Assert3('36-VARIANTA RON: G.suma=400.00', suma, 400.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO DcLog WITH ' FAIL 36: G (RON) negasit'
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey3 AND tip_rand == 'T'
|
||||
IF FOUND()
|
||||
=Assert3('37-VARIANTA RON: T.suma=336.00 ((2000.00-400.00)*21%)', suma, 336.00)
|
||||
=Assert3('38-VARIANTA RON: T.suma_val=0 (fara valuta)', NVL(suma_val,0), 0)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DcLog WITH ' FAIL 37-38: T (RON) negasit'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 6, 'varianta factura RON + discount verificata - vezi log'
|
||||
|
||||
DO DcLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO DcLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO DcLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 7, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO DcLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE AdaugaFactura
|
||||
*-- FACTURA EUR curs 5.23, 1000 EUR, TVA pe furnizor (F, normal - discountul e independent
|
||||
*-- de ramura TVA); baza discountul e in EUR (aceeasi unitate ca suma facturii).
|
||||
LPARAMETERS tnNract, tcPartener, tnIdPartener, tnDiscBazaVal
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = tnNract
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = tnIdPartener
|
||||
goDlg.cPartener = tcPartener
|
||||
goDlg.cExplicatia = 'Import marfa ' + tcPartener
|
||||
goDlg.nSuma = 1000
|
||||
goDlg.nSumaLei = 0
|
||||
goDlg.nCurs = 5.23
|
||||
goDlg.nIdValuta = 978
|
||||
goDlg.cValuta = 'EUR'
|
||||
goDlg.nIdExplicatieTva = 208
|
||||
goDlg.cExplicatieTva = 'ACH. INT. 21%'
|
||||
goDlg.optTipTva.Value = 1 && F = furnizor (normal)
|
||||
goDlg.chkInValutaCont.Value = 1
|
||||
goDlg.chkParticipaValuta.Value = 1
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO DcLog WITH 'DOC ' + TRANSFORM(tnNract) + ': valideaza = ' + TRANSFORM(goDlg.valideaza())
|
||||
DO ConstruiesteToDlgF1F2 WITH ROUND(tnDiscBazaVal*5.23,4), tnDiscBazaVal
|
||||
DO DcLog WITH 'DOC ' + TRANSFORM(tnNract) + ': do_adauga_factura = ' + TRANSFORM(goObj.do_adauga_factura(goT))
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE AdaugaFacturaRon
|
||||
*-- Varianta FACTURA IN RON (fara valuta) + discount - disc_baza_val=0.
|
||||
LPARAMETERS tnNract, tcPartener, tnIdPartener, tnDiscBazaLei
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = tnNract
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = tnIdPartener
|
||||
goDlg.cPartener = tcPartener
|
||||
goDlg.cExplicatia = 'Achizitie ' + tcPartener
|
||||
goDlg.nSuma = 2000
|
||||
goDlg.nSumaLei = 0
|
||||
goDlg.nCurs = 0
|
||||
goDlg.nIdExplicatieTva = 208
|
||||
goDlg.cExplicatieTva = 'ACH. INT. 21%'
|
||||
goDlg.optTipTva.Value = 1
|
||||
goDlg.chkInValutaCont.Value = 0
|
||||
goDlg.chkParticipaValuta.Value = 1
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO DcLog WITH 'DOC ' + TRANSFORM(tnNract) + ' (RON): valideaza = ' + TRANSFORM(goDlg.valideaza())
|
||||
DO ConstruiesteToDlgF1F2 WITH tnDiscBazaLei, 0
|
||||
DO DcLog WITH 'DOC ' + TRANSFORM(tnNract) + ' (RON): do_adauga_factura = ' + TRANSFORM(goObj.do_adauga_factura(goT))
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE ConstruiesteToDlgF1F2
|
||||
*-- Runda32: doar disc_baza_lei/disc_baza_val (are_discount/disc_tva_lei/disc_tva_val
|
||||
*-- eliminate din construieste_todlg).
|
||||
LPARAMETERS tnDiscBazaLei, tnDiscBazaVal
|
||||
goT = CREATEOBJECT('Empty')
|
||||
=ADDPROPERTY(goT,'serie_act',ALLTRIM(NVL(goDlg.cSerieAct,'')))
|
||||
=ADDPROPERTY(goT,'nract',goDlg.nNract)
|
||||
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
|
||||
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
|
||||
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
|
||||
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
|
||||
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
|
||||
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
|
||||
=ADDPROPERTY(goT,'suma',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,IIF(goDlg.nSumaLei<>0,goDlg.nSumaLei,ROUND(goDlg.nSuma*goDlg.nCurs,gnPC)),goDlg.nSuma))
|
||||
=ADDPROPERTY(goT,'suma_val',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,goDlg.nSuma,0))
|
||||
=ADDPROPERTY(goT,'in_valuta',goDlg.chkInValutaCont.Value)
|
||||
=ADDPROPERTY(goT,'participa_valuta',(goDlg.chkParticipaValuta.Value=1))
|
||||
=ADDPROPERTY(goT,'id_valuta',IIF(goDlg.chkInValutaCont.Value=1,goDlg.nIdValuta,0))
|
||||
=ADDPROPERTY(goT,'curs',IIF(goDlg.chkInValutaCont.Value=1,goDlg.nCurs,0))
|
||||
=ADDPROPERTY(goT,'nume_val',IIF(goDlg.chkInValutaCont.Value=1,ALLTRIM(NVL(goDlg.cValuta,'')),''))
|
||||
=ADDPROPERTY(goT,'cTipTva',IIF(goDlg.optTipTva.Value=1,'F',IIF(goDlg.optTipTva.Value=2,'D','N')))
|
||||
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
|
||||
=ADDPROPERTY(goT,'dvi_serie','')
|
||||
=ADDPROPERTY(goT,'dvi_nract',0)
|
||||
=ADDPROPERTY(goT,'dvi_dataact',DATE())
|
||||
=ADDPROPERTY(goT,'dvi_id_fdoc',0)
|
||||
=ADDPROPERTY(goT,'dvi_fdoc','')
|
||||
=ADDPROPERTY(goT,'dvi_id_partc',0)
|
||||
=ADDPROPERTY(goT,'dvi_partc','')
|
||||
=ADDPROPERTY(goT,'dvi_scc','401')
|
||||
=ADDPROPERTY(goT,'dvi_tva_lei',0)
|
||||
=ADDPROPERTY(goT,'dvi_tva_val',0)
|
||||
=ADDPROPERTY(goT,'dvi_in_valuta',.F.)
|
||||
=ADDPROPERTY(goT,'dvi_id_valuta',0)
|
||||
=ADDPROPERTY(goT,'dvi_curs',0)
|
||||
=ADDPROPERTY(goT,'dvi_nume_val','')
|
||||
=ADDPROPERTY(goT,'dvi_valuta_proprie',0)
|
||||
*-- Runda32: discount financiar - doar baza (fara are_discount/disc_tva_lei/disc_tva_val)
|
||||
=ADDPROPERTY(goT,'disc_baza_lei',tnDiscBazaLei)
|
||||
=ADDPROPERTY(goT,'disc_baza_val',tnDiscBazaVal)
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaRulTemp
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp ( ;
|
||||
id_rul N(20,0), an N(4,0), luna N(2,0), cod N(20,0);
|
||||
, serie C(100), nnir N(20,0), id_articol N(10,0), denumire C(100);
|
||||
, codmat C(50), codmatf C(50), codbare C(50), um C(20);
|
||||
, id_gestiune N(5,0), nume_gestiune C(50), cgest C(20), nr_pag N(2,0);
|
||||
, gestionar C(50), comisie_receptie1 C(50), comisie_receptie2 C(50), comisie_receptie3 C(50);
|
||||
, cant N(14,3), cante N(14,3), cont C(10), acont C(20);
|
||||
, pret N(18,4), tva N(18,4), valoare N(18,4), valtva N(18,4);
|
||||
, proc_tva N(5,2), pretv N(18,4), pretvtva N(18,4), tvav N(18,4);
|
||||
, valoarev N(18,4), valtvav N(18,4), proc_tvav N(5,2), adaos N(18,4);
|
||||
, adaos_tva N(18,4), valoare_adaos N(18,4), valtva_adaos N(18,4), procent N(10,3);
|
||||
, discunitar N(18,4), discount_tva N(18,4), valoare_discount N(18,4), valtva_discount N(18,4);
|
||||
, proc_disc N(7,3), pretd N(14,4), curs N(18,4), id_valuta N(10,0);
|
||||
, nume_val C(20), id_lucrare N(20,0), nrord C(100), id_responsabil N(10,0);
|
||||
, nresp C(100), resp_marca N(18,4), dataact T, id_util N(5,0);
|
||||
, util C(30), dataora T, id_sectie N(5,0), sectie C(50);
|
||||
, csectie C(10), alcooltutun N(1,0), datain T, dataout T;
|
||||
, id_fact N(20,0), id_gestiunec N(10,0), nume_gestiunec C(50), cgestc C(20);
|
||||
, id_responsabilc N(5,0), id_reteta N(10,0), reteta C(50), nrespc C(100);
|
||||
, respc_marca N(18,4), id_set N(20,0), id_tip_rulaj N(10,0), tip_rulaj C(50);
|
||||
, id_obiect_depozit N(10,0), id_rul_aux N(10,0), nract N(20,0), serie_act C(10);
|
||||
, dataoras T, id_utils N(10,0), lot C(30), adata_expirare T;
|
||||
, id_sucursala N(5,0), sucursala C(250), id_part_rez N(10,0), part_rez C(100);
|
||||
, id_lucrare_rez N(10,0), nrord_rez C(100), subgrupa C(100), grupa C(100);
|
||||
, id_subgrupa N(5,0), id_grupa N(5,0), in_stoc N(1,0), in_crm N(1,0);
|
||||
, id_furnizor N(10,0), furnizor C(100), id_jtva_coloana N(4,0), explicatie_tva C(100);
|
||||
, taxcode N(6,0), taxname C(254), saft_procent N(18,4), codnc8 C(20);
|
||||
, id_tara_origine N(4,0), cod_tara_origine C(5), tara_origine C(50), greutate N(12,4);
|
||||
, fdoc C(30), id_fdoc N(18,4);
|
||||
, pret_lei N(18,4), pret_val N(14,4), cota_tva N(6,2))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaIntrodc
|
||||
*-- Runda30 (F1/pas2): coloane NOI rand_dvi N(1), valuta_proprie N(1) fata de structura veche.
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
FUNCTION RECCOUNT_ACTIVE
|
||||
LPARAMETERS tcAlias
|
||||
LOCAL lnSel, lnCnt
|
||||
lnSel = SELECT()
|
||||
SELECT (tcAlias)
|
||||
COUNT TO lnCnt FOR !DELETED()
|
||||
SELECT (lnSel)
|
||||
RETURN lnCnt
|
||||
ENDFUNC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO DcLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO DcLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE AssertStr
|
||||
LPARAMETERS tcLabel, tcActual, tcExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF tcActual == tcExpected
|
||||
pnPass = pnPass + 1
|
||||
DO DcLog WITH ' PASS ' + tcLabel + ' (=[' + tcActual + '])'
|
||||
ELSE
|
||||
DO DcLog WITH ' FAIL ' + tcLabel + ' (actual=[' + tcActual + '] asteptat=[' + tcExpected + '])'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DcErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO DcLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DcLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES (IIF(TYPE('gcMockAcontCrt') = 'C', gcMockAcontCrt, ''))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES ('371', '4')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (208, 'ACH. INT. 21%', 1, 0, 'RO21B', 21, 209, 1, 1, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (209, 'TVA ACH. INT. 21%', 1, 0, 'RO21T', 21, 1, 2, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 3, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 4, 301204)
|
||||
ENDPROC
|
||||
12
utile/Teste/achizitie_import/test_discount_factura.ps1
Normal file
12
utile/Teste/achizitie_import/test_discount_factura.ps1
Normal file
@@ -0,0 +1,12 @@
|
||||
# test_discount_factura.ps1 - wrapper peste harness-ul generic pentru discountul financiar pe
|
||||
# factura de import (model B/G/T, un singur rand G) - Runda32.
|
||||
# powershell -ExecutionPolicy Bypass -File test_discount_factura.ps1
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Teste = $PSScriptRoot
|
||||
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
|
||||
-TestPrg (Join-Path $Teste 'test_discount_factura.prg') `
|
||||
-Steps @('doc1_creat','doc1_g_t_verificat','articol_stabilitate','nir_best_effort','stergere_document','discount_zero','factura_ron','final') `
|
||||
-ShotsDir (Join-Path $Teste 'screenshots_discount_factura') `
|
||||
-SyncDir (Join-Path $Teste 'uisync_discount_factura') `
|
||||
-StepTimeoutSec 180 `
|
||||
-ReadyTimeoutSec 180
|
||||
723
utile/Teste/achizitie_import/test_discount_multicota.prg
Normal file
723
utile/Teste/achizitie_import/test_discount_multicota.prg
Normal file
@@ -0,0 +1,723 @@
|
||||
* test_discount_multicota.prg
|
||||
* Runda32 (model B/G/T): factura de import cu articole pe DOUA cote TVA (21% si 11%) + discount
|
||||
* financiar. Verifica distribuirea discountului in sparge_document (calc_baze_cota_creditor +
|
||||
* lnFactorDisc): fiecare rand T e scalat cu ACELASI factor de discount ((baza_grup_tot -
|
||||
* discount) / baza_grup_tot), aplicat pe baza PROPRIE a cotei, nu pe un singur T global.
|
||||
* Flux REAL: dialogul `import_adauga_factura` + doua `do_adauga_articol()` (cote diferite) +
|
||||
* `sincronizeaza()` (declanseaza sparge_document, documentul e principal si unic).
|
||||
*
|
||||
* Discountul se sparge si el pe cote (sparge_discount), proportional cu bazele: fiecare rand G
|
||||
* poarta cota lui, iar randurile S poarta cota articolelor lor - baza si TVA-ul sunt concordante.
|
||||
* Scenariu: factura EUR curs 5, 1500 EUR (=1000 la 21% + 500 la 11%, fara diferenta reziduala),
|
||||
* discount baza 150 EUR (10% din total):
|
||||
* - lnFactorDisc = (1500-150)/1500 = 0.9
|
||||
* - T(21%): suma_val = ROUND(1000*0.9*21/100,2) = 189.00, suma = 945.00
|
||||
* - T(11%): suma_val = ROUND(500*0.9*11/100,2) = 49.50, suma = 247.50
|
||||
* - suma T-urilor = 238.50 (val) / 1192.50 (lei) - fara reziduu de rotunjire (numere curate).
|
||||
*
|
||||
* ASUMPTII: jtva_coloane2 are 2 familii import (FO) la 21%/11% (id 220/222, coloana_jc
|
||||
* FO21B/FO11B) ca gaseste_jtva_cota sa gaseasca perechea corecta pentru a doua cota; articolele
|
||||
* au conturi DIFERITE (212/371), dar fara randuri S preexistente calc_baze_cota_creditor le da
|
||||
* la amandoua ACELASI creditor fallback (scc/ascc-ul randului B), deci crsGrupCota le separa
|
||||
* DOAR dupa cota_tva (grupare pe cota_tva+scc+ascc, nu pe cont).
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_discount_multicota.ps1
|
||||
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_discount_multicota_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_discount_multicota\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO McErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO McLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO McLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_cauta_nom_articole.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO McLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
PUBLIC goMockValuta
|
||||
goMockValuta = CREATEOBJECT('Custom')
|
||||
goMockValuta.AddProperty('id_valuta', 978)
|
||||
goMockValuta.AddProperty('nume_val', 'EUR')
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnButon
|
||||
STORE 2 TO gnButon
|
||||
PUBLIC gcMockArtCodmat, gcMockAcontCrt
|
||||
gcMockArtCodmat = ''
|
||||
gcMockAcontCrt = ''
|
||||
PUBLIC gnMockRaspuns
|
||||
gnMockRaspuns = 6
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (moneda principala EUR, curs 5) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 5)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 601)
|
||||
poAct.AddProperty('partc', 'MULTI SUPPLY SRL')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: DOUA familii import (FO), 21% si 11% -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (3, 222, 'ACH. IMP. 11%', 1, 0, 1, 'FO11B', 'FO11T', 11, 223)
|
||||
INSERT INTO jtva_coloane2 VALUES (4, 223, 'TVA ACH. IMP. 11%', 1, 0, 1, 'FO11T', '', 11, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301205-Import de bunuri cota 11%', 301205, '', 11, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 220, 21, 'ACH. IMP. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 221, 21, 'TVA ACH. IMP. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
DO CreeazaRulTemp
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO McLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F.)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO McLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
*========================= FACTURA: 1500 EUR (1000@21% + 500@11%), discount 150 EUR =========================
|
||||
PUBLIC goDlg, goT, gcDocKey1
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = 16000
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = 601
|
||||
goDlg.cPartener = 'MULTI SUPPLY SRL'
|
||||
goDlg.cExplicatia = 'Import marfa multicota'
|
||||
goDlg.nSuma = 1500
|
||||
goDlg.nSumaLei = 0
|
||||
goDlg.nCurs = 5
|
||||
goDlg.nIdValuta = 978
|
||||
goDlg.cValuta = 'EUR'
|
||||
goDlg.nIdExplicatieTva = 220
|
||||
goDlg.cExplicatieTva = 'ACH. IMP. 21%'
|
||||
goDlg.optTipTva.Value = 1
|
||||
goDlg.chkInValutaCont.Value = 1
|
||||
goDlg.chkParticipaValuta.Value = 1
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO McLog WITH 'valideaza = ' + TRANSFORM(goDlg.valideaza())
|
||||
|
||||
goT = CREATEOBJECT('Empty')
|
||||
=ADDPROPERTY(goT,'serie_act','')
|
||||
=ADDPROPERTY(goT,'nract',goDlg.nNract)
|
||||
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
|
||||
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
|
||||
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
|
||||
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
|
||||
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
|
||||
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
|
||||
=ADDPROPERTY(goT,'suma',ROUND(goDlg.nSuma*goDlg.nCurs,gnPC))
|
||||
=ADDPROPERTY(goT,'suma_val',goDlg.nSuma)
|
||||
=ADDPROPERTY(goT,'in_valuta',goDlg.chkInValutaCont.Value)
|
||||
=ADDPROPERTY(goT,'participa_valuta',.T.)
|
||||
=ADDPROPERTY(goT,'id_valuta',goDlg.nIdValuta)
|
||||
=ADDPROPERTY(goT,'curs',goDlg.nCurs)
|
||||
=ADDPROPERTY(goT,'nume_val',ALLTRIM(NVL(goDlg.cValuta,'')))
|
||||
=ADDPROPERTY(goT,'cTipTva','F')
|
||||
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
|
||||
=ADDPROPERTY(goT,'dvi_serie','')
|
||||
=ADDPROPERTY(goT,'dvi_nract',0)
|
||||
=ADDPROPERTY(goT,'dvi_dataact',DATE())
|
||||
=ADDPROPERTY(goT,'dvi_id_fdoc',0)
|
||||
=ADDPROPERTY(goT,'dvi_fdoc','')
|
||||
=ADDPROPERTY(goT,'dvi_id_partc',0)
|
||||
=ADDPROPERTY(goT,'dvi_partc','')
|
||||
=ADDPROPERTY(goT,'dvi_scc','401')
|
||||
=ADDPROPERTY(goT,'dvi_tva_lei',0)
|
||||
=ADDPROPERTY(goT,'dvi_tva_val',0)
|
||||
=ADDPROPERTY(goT,'dvi_in_valuta',.F.)
|
||||
=ADDPROPERTY(goT,'dvi_id_valuta',0)
|
||||
=ADDPROPERTY(goT,'dvi_curs',0)
|
||||
=ADDPROPERTY(goT,'dvi_nume_val','')
|
||||
=ADDPROPERTY(goT,'dvi_valuta_proprie',0)
|
||||
=ADDPROPERTY(goT,'disc_baza_lei',ROUND(150*5,gnPC))
|
||||
=ADDPROPERTY(goT,'disc_baza_val',150)
|
||||
|
||||
LOCAL llOkAdauga
|
||||
llOkAdauga = goObj.do_adauga_factura(goT)
|
||||
=Assert3('1-do_adauga_factura(goT) reuseste', IIF(llOkAdauga,1,0), 1)
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT introdc
|
||||
SET ORDER TO
|
||||
LOCATE FOR nract = 16000 AND tip_rand == 'B'
|
||||
IF FOUND()
|
||||
gcDocKey1 = ALLTRIM(NVL(doc_key,''))
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO HarnessStep WITH 0, 'factura creata, doc_key=' + gcDocKey1
|
||||
|
||||
*========================= DOUA ARTICOLE, COTE DIFERITE (21% si 11%) =========================
|
||||
gcMockArtCodmat = 'ART-BULD-212'
|
||||
gcMockAcontCrt = ''
|
||||
TRY
|
||||
goObj.do_adauga_articol()
|
||||
CATCH TO loExcA1
|
||||
DO McLog WITH 'EROARE do_adauga_articol (1) ' + TRANSFORM(loExcA1.ErrorNo) + ' [' + loExcA1.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-BULD-212'
|
||||
IF FOUND()
|
||||
REPLACE cant WITH 1, pret_val WITH 1000, pretd WITH 1000, pret WITH ROUND(1000*5,4), ;
|
||||
pret_lei WITH ROUND(1000*5,4), cota_tva WITH 21
|
||||
ENDIF
|
||||
|
||||
gcMockArtCodmat = 'ART-A8-371'
|
||||
TRY
|
||||
goObj.do_adauga_articol()
|
||||
CATCH TO loExcA2
|
||||
DO McLog WITH 'EROARE do_adauga_articol (2) ' + TRANSFORM(loExcA2.ErrorNo) + ' [' + loExcA2.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-A8-371'
|
||||
IF FOUND()
|
||||
REPLACE cant WITH 1, pret_val WITH 500, pretd WITH 500, pret WITH ROUND(500*5,4), ;
|
||||
pret_lei WITH ROUND(500*5,4), cota_tva WITH 11
|
||||
ENDIF
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
=Assert3('2-doua articole in rul_temp', RECCOUNT_ACTIVE('rul_temp'), 2)
|
||||
|
||||
DO HarnessStep WITH 1, 'articole (21% si 11%) adaugate'
|
||||
|
||||
*========================= sincronizeaza() (declanseaza sparge_document) =========================
|
||||
LOCAL llEroareSync
|
||||
llEroareSync = .F.
|
||||
TRY
|
||||
goObj.sincronizeaza()
|
||||
CATCH TO loExcS
|
||||
llEroareSync = .T.
|
||||
DO McLog WITH 'EROARE sincronizeaza() ' + TRANSFORM(loExcS.ErrorNo) + ' [' + loExcS.Message + '] in ' + loExcS.Procedure + ':' + TRANSFORM(loExcS.LineNo)
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
=Assert3('3-sincronizeaza() fara eroare', IIF(llEroareSync,0,1), 1)
|
||||
|
||||
*========================= G: discountul se sparge pe cote (baza TVA-ului) =========================
|
||||
LOCAL lnCntG, lnSumGVal, lnSumG
|
||||
STORE 0 TO lnCntG, lnSumGVal, lnSumG
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'G'
|
||||
lnCntG = lnCntG + 1
|
||||
lnSumGVal = lnSumGVal + suma_val
|
||||
lnSumG = lnSumG + suma
|
||||
ENDSCAN
|
||||
=Assert3('4-doua randuri G (unul pe cota)', lnCntG, 2)
|
||||
=Assert3('4a-total discount valuta pastrat', lnSumGVal, 150.00)
|
||||
=Assert3('4b-total discount lei pastrat', lnSumG, 750.00)
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'G' AND ptva == 21
|
||||
=Assert3('5-G(21%) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('5a-G(21%).suma_val=100.00 (150*1000/1500)', suma_val, 100.00)
|
||||
=Assert3('5b-G(21%).suma=500.00', suma, 500.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO McLog WITH ' FAIL 5a-5b: G(21%) negasit'
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'G' AND ptva == 11
|
||||
=Assert3('6-G(11%) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('6a-G(11%).suma_val=50.00 (150*500/1500)', suma_val, 50.00)
|
||||
=Assert3('6b-G(11%).suma=250.00', suma, 250.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO McLog WITH ' FAIL 6a-6b: G(11%) negasit'
|
||||
ENDIF
|
||||
|
||||
*========================= T-uri: cate unul pe cota, scalate cu acelasi factor de discount =========================
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'T' AND ptva == 21
|
||||
=Assert3('7-T(21%) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('8-T(21%).suma_val=189.00 (1000*0.9*21%)', suma_val, 189.00)
|
||||
=Assert3('9-T(21%).suma=945.00', suma, 945.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO McLog WITH ' FAIL 8-9: T(21%) negasit'
|
||||
ENDIF
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'T' AND ptva == 11
|
||||
=Assert3('10-T(11%) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('11-T(11%).suma_val=49.50 (500*0.9*11%)', suma_val, 49.50)
|
||||
=Assert3('12-T(11%).suma=247.50', suma, 247.50)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO McLog WITH ' FAIL 11-12: T(11%) negasit'
|
||||
ENDIF
|
||||
|
||||
LOCAL lnCntT, lnSumTVal, lnSumT
|
||||
STORE 0 TO lnCntT, lnSumTVal, lnSumT
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'T'
|
||||
lnCntT = lnCntT + 1
|
||||
lnSumTVal = lnSumTVal + suma_val
|
||||
lnSumT = lnSumT + suma
|
||||
ENDSCAN
|
||||
=Assert3('13-exact 2 randuri T (o cota fiecare)', lnCntT, 2)
|
||||
=Assert3('14-suma T-urilor (valuta) = 238.50, fara reziduu de rotunjire', lnSumTVal, 238.50)
|
||||
=Assert3('15-suma T-urilor (lei) = 1192.50, fara reziduu de rotunjire', lnSumT, 1192.50)
|
||||
|
||||
*========================= S: cota randului de baza = cota articolelor lui =========================
|
||||
LOCAL lnCntS
|
||||
lnCntS = 0
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'S'
|
||||
lnCntS = lnCntS + 1
|
||||
ENDSCAN
|
||||
=Assert3('16-doua randuri S', lnCntS, 2)
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'S' AND ptva == 21
|
||||
=Assert3('17-S cu cota 21 (articolul de 1000)', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('17a-S(21%).suma_val=1000.00', suma_val, 1000.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO McLog WITH ' FAIL 17a: S(21%) negasit'
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'S' AND ptva == 11
|
||||
=Assert3('18-S cu cota 11 (articolul de 500)', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('18a-S(11%).suma_val=500.00', suma_val, 500.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO McLog WITH ' FAIL 18a: S(11%) negasit'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 2, 'T-uri multicota verificate - suma val=' + TRANSFORM(lnSumTVal) + ' lei=' + TRANSFORM(lnSumT)
|
||||
|
||||
DO McLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO McLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO McLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 3, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO McLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE CreeazaRulTemp
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp ( ;
|
||||
id_rul N(20,0), an N(4,0), luna N(2,0), cod N(20,0);
|
||||
, serie C(100), nnir N(20,0), id_articol N(10,0), denumire C(100);
|
||||
, codmat C(50), codmatf C(50), codbare C(50), um C(20);
|
||||
, id_gestiune N(5,0), nume_gestiune C(50), cgest C(20), nr_pag N(2,0);
|
||||
, gestionar C(50), comisie_receptie1 C(50), comisie_receptie2 C(50), comisie_receptie3 C(50);
|
||||
, cant N(14,3), cante N(14,3), cont C(10), acont C(20);
|
||||
, pret N(18,4), tva N(18,4), valoare N(18,4), valtva N(18,4);
|
||||
, proc_tva N(5,2), pretv N(18,4), pretvtva N(18,4), tvav N(18,4);
|
||||
, valoarev N(18,4), valtvav N(18,4), proc_tvav N(5,2), adaos N(18,4);
|
||||
, adaos_tva N(18,4), valoare_adaos N(18,4), valtva_adaos N(18,4), procent N(10,3);
|
||||
, discunitar N(18,4), discount_tva N(18,4), valoare_discount N(18,4), valtva_discount N(18,4);
|
||||
, proc_disc N(7,3), pretd N(14,4), curs N(18,4), id_valuta N(10,0);
|
||||
, nume_val C(20), id_lucrare N(20,0), nrord C(100), id_responsabil N(10,0);
|
||||
, nresp C(100), resp_marca N(18,4), dataact T, id_util N(5,0);
|
||||
, util C(30), dataora T, id_sectie N(5,0), sectie C(50);
|
||||
, csectie C(10), alcooltutun N(1,0), datain T, dataout T;
|
||||
, id_fact N(20,0), id_gestiunec N(10,0), nume_gestiunec C(50), cgestc C(20);
|
||||
, id_responsabilc N(5,0), id_reteta N(10,0), reteta C(50), nrespc C(100);
|
||||
, respc_marca N(18,4), id_set N(20,0), id_tip_rulaj N(10,0), tip_rulaj C(50);
|
||||
, id_obiect_depozit N(10,0), id_rul_aux N(10,0), nract N(20,0), serie_act C(10);
|
||||
, dataoras T, id_utils N(10,0), lot C(30), adata_expirare T;
|
||||
, id_sucursala N(5,0), sucursala C(250), id_part_rez N(10,0), part_rez C(100);
|
||||
, id_lucrare_rez N(10,0), nrord_rez C(100), subgrupa C(100), grupa C(100);
|
||||
, id_subgrupa N(5,0), id_grupa N(5,0), in_stoc N(1,0), in_crm N(1,0);
|
||||
, id_furnizor N(10,0), furnizor C(100), id_jtva_coloana N(4,0), explicatie_tva C(100);
|
||||
, taxcode N(6,0), taxname C(254), saft_procent N(18,4), codnc8 C(20);
|
||||
, id_tara_origine N(4,0), cod_tara_origine C(5), tara_origine C(50), greutate N(12,4);
|
||||
, fdoc C(30), id_fdoc N(18,4);
|
||||
, pret_lei N(18,4), pret_val N(14,4), cota_tva N(6,2))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaIntrodc
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
FUNCTION RECCOUNT_ACTIVE
|
||||
LPARAMETERS tcAlias
|
||||
LOCAL lnSel, lnCnt
|
||||
lnSel = SELECT()
|
||||
SELECT (tcAlias)
|
||||
COUNT TO lnCnt FOR !DELETED()
|
||||
SELECT (lnSel)
|
||||
RETURN lnCnt
|
||||
ENDFUNC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO McLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO McLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE McErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO McLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE McLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES (IIF(TYPE('gcMockAcontCrt') = 'C', gcMockAcontCrt, ''))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VCONFIG_CONT_IREG' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (contpart C(10), fel_cont N(1), cu_inregistrari N(1), ;
|
||||
explic_cont C(100), exceptie C(10), pozitie N(1), invers N(1), gasit N(1))
|
||||
INSERT INTO (m.tcCursor) VALUES ('401', 0, 0, 'Furnizori', '', 0, 0, 0)
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 1, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 2, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (222, 'ACH. IMP. 11%', 1, 0, 'FO11B', 11, 223, 1, 3, 301205)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (223, 'TVA ACH. IMP. 11%', 1, 0, 'FO11T', 11, 1, 4, 301205)
|
||||
ENDPROC
|
||||
12
utile/Teste/achizitie_import/test_discount_multicota.ps1
Normal file
12
utile/Teste/achizitie_import/test_discount_multicota.ps1
Normal file
@@ -0,0 +1,12 @@
|
||||
# test_discount_multicota.ps1 - wrapper peste harness-ul generic pentru discountul financiar
|
||||
# distribuit pe doua cote TVA (21%/11%) - Runda32.
|
||||
# powershell -ExecutionPolicy Bypass -File test_discount_multicota.ps1
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Teste = $PSScriptRoot
|
||||
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
|
||||
-TestPrg (Join-Path $Teste 'test_discount_multicota.prg') `
|
||||
-Steps @('factura_creata','articole_adaugate','sincronizare','final') `
|
||||
-ShotsDir (Join-Path $Teste 'screenshots_discount_multicota') `
|
||||
-SyncDir (Join-Path $Teste 'uisync_discount_multicota') `
|
||||
-StepTimeoutSec 180 `
|
||||
-ReadyTimeoutSec 180
|
||||
624
utile/Teste/achizitie_import/test_discount_valuta.prg
Normal file
624
utile/Teste/achizitie_import/test_discount_valuta.prg
Normal file
@@ -0,0 +1,624 @@
|
||||
* test_discount_valuta.prg
|
||||
* Runda32 (model B/G/T): discount financiar pe factura de import IN VALUTA - verifica suma
|
||||
* (lei) si suma_val (valuta) pe randul G (discount) si pe randul T (TVA pe baza neta), pentru
|
||||
* DOUA valute diferite (EUR cu suma_lei introdusa manual, GBP cu suma_lei auto-calculata din
|
||||
* curs) - discountul insusi e introdus in valuta facturii (aceeasi unitate ca txtSuma).
|
||||
*
|
||||
* DOC1 (EUR, curs 4.50, 1000 EUR, nSumaLei introdus manual = 4500.00):
|
||||
* discount baza = 200 EUR -> disc_baza_lei=900.00, disc_baza_val=200.00
|
||||
* G.suma=900.00, G.suma_val=200.00
|
||||
* T.suma = (4500.00-900.00)*21% = 756.00, T.suma_val = (1000.00-200.00)*21% = 168.00
|
||||
* DOC2 (GBP, curs 5.75, 500 GBP, nSumaLei auto = ROUND(500*5.75,2) = 2875.00):
|
||||
* discount baza = 60 GBP -> disc_baza_lei=345.00, disc_baza_val=60.00
|
||||
* G.suma=345.00, G.suma_val=60.00
|
||||
* T.suma = (2875.00-345.00)*21% = 531.30, T.suma_val = (500.00-60.00)*21% = 92.40
|
||||
*
|
||||
* Flux REAL: dialogul `import_adauga_factura` (toDlg construit inline, capcana l -
|
||||
* CREATEOBJECT/ADDPROPERTY nu merg dintr-o procedura in acest runtime headless).
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_discount_valuta.ps1
|
||||
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_discount_valuta_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_discount_valuta\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO DvErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO DvLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO DvLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_cauta_nom_articole.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO DvLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
PUBLIC goMockValuta
|
||||
goMockValuta = CREATEOBJECT('Custom')
|
||||
goMockValuta.AddProperty('id_valuta', 978)
|
||||
goMockValuta.AddProperty('nume_val', 'EUR')
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnButon
|
||||
STORE 2 TO gnButon
|
||||
PUBLIC gcMockArtCodmat, gcMockAcontCrt
|
||||
gcMockArtCodmat = ''
|
||||
gcMockAcontCrt = ''
|
||||
PUBLIC gnMockRaspuns
|
||||
gnMockRaspuns = 6
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (moneda principala EUR, curs 4.50) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 4.50)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 601)
|
||||
poAct.AddProperty('partc', 'EURO IMPEX')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: perechi reale 21% -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 208, 'ACH. INT. 21%', 1, 0, 1, 'RO21B', 'RO21T', 21, 209)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 209, 'TVA ACH. INT. 21%', 1, 0, 1, 'RO21T', '', 21, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (3, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (4, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 208, 21, 'ACH. INT. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 209, 21, 'TVA ACH. INT. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
DO CreeazaRulTemp
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO DvLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F.)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO DvLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
*========================= DOC1: EUR, nSumaLei introdus manual =========================
|
||||
PUBLIC goDlg, goT, gcDocKey1
|
||||
DO AdaugaFacturaValuta WITH 17000, 'EURO IMPEX', 601, 978, 'EUR', 4.50, 1000, 4500.00, 200.00
|
||||
SELECT introdc
|
||||
SET ORDER TO
|
||||
LOCATE FOR nract = 17000 AND tip_rand == 'B'
|
||||
IF FOUND()
|
||||
gcDocKey1 = ALLTRIM(NVL(doc_key,''))
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'B'
|
||||
=Assert3('1-DOC1(EUR): B.suma=4500.00 (nSumaLei manual)', suma, 4500.00)
|
||||
=Assert3('2-DOC1(EUR): B.suma_val=1000.00', suma_val, 1000.00)
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'G'
|
||||
=Assert3('3-DOC1(EUR): randul G gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('4-DOC1(EUR): G.suma=900.00', suma, 900.00)
|
||||
=Assert3('5-DOC1(EUR): G.suma_val=200.00', suma_val, 200.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DvLog WITH ' FAIL 4-5: G (DOC1) negasit'
|
||||
ENDIF
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'T'
|
||||
=Assert3('6-DOC1(EUR): randul T gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('7-DOC1(EUR): T.suma=756.00 ((4500-900)*21%)', suma, 756.00)
|
||||
=Assert3('8-DOC1(EUR): T.suma_val=168.00 ((1000-200)*21%)', suma_val, 168.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DvLog WITH ' FAIL 7-8: T (DOC1) negasit'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 0, 'DOC1 (EUR) verificat'
|
||||
|
||||
*========================= DOC2: GBP, nSumaLei auto-calculat din curs =========================
|
||||
PUBLIC gcDocKey2
|
||||
DO AdaugaFacturaValuta WITH 17001, 'BRITISH TRADE LTD', 604, 826, 'GBP', 5.75, 500, 0, 60.00
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 17001 AND tip_rand == 'B'
|
||||
IF FOUND()
|
||||
gcDocKey2 = ALLTRIM(NVL(doc_key,''))
|
||||
ENDIF
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey2 AND tip_rand == 'B'
|
||||
=Assert3('9-DOC2(GBP): B.suma=2875.00 (auto ROUND(500*5.75,2))', suma, 2875.00)
|
||||
=Assert3('10-DOC2(GBP): B.suma_val=500.00', suma_val, 500.00)
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey2 AND tip_rand == 'G'
|
||||
=Assert3('11-DOC2(GBP): randul G gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('12-DOC2(GBP): G.suma=345.00', suma, 345.00)
|
||||
=Assert3('13-DOC2(GBP): G.suma_val=60.00', suma_val, 60.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DvLog WITH ' FAIL 12-13: G (DOC2) negasit'
|
||||
ENDIF
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey2 AND tip_rand == 'T'
|
||||
=Assert3('14-DOC2(GBP): randul T gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('15-DOC2(GBP): T.suma=531.30 ((2875-345)*21%)', suma, 531.30)
|
||||
=Assert3('16-DOC2(GBP): T.suma_val=92.40 ((500-60)*21%)', suma_val, 92.40)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DvLog WITH ' FAIL 15-16: T (DOC2) negasit'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 1, 'DOC2 (GBP) verificat'
|
||||
|
||||
DO DvLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO DvLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO DvLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 2, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO DvLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE AdaugaFacturaValuta
|
||||
*-- factura in valuta oarecare (id/nume/curs date), discount in ACEEASI valuta ca suma.
|
||||
LPARAMETERS tnNract, tcPartener, tnIdPartener, tnIdValuta, tcValuta, tnCurs, tnSuma, tnSumaLei, tnDiscBazaVal
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = tnNract
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = tnIdPartener
|
||||
goDlg.cPartener = tcPartener
|
||||
goDlg.cExplicatia = 'Import marfa ' + tcPartener
|
||||
goDlg.nSuma = tnSuma
|
||||
goDlg.nSumaLei = tnSumaLei
|
||||
goDlg.nCurs = tnCurs
|
||||
goDlg.nIdValuta = tnIdValuta
|
||||
goDlg.cValuta = tcValuta
|
||||
goDlg.nIdExplicatieTva = 208
|
||||
goDlg.cExplicatieTva = 'ACH. INT. 21%'
|
||||
goDlg.optTipTva.Value = 1
|
||||
goDlg.chkInValutaCont.Value = 1
|
||||
goDlg.chkParticipaValuta.Value = 1
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO DvLog WITH 'DOC ' + TRANSFORM(tnNract) + ' (' + tcValuta + '): valideaza = ' + TRANSFORM(goDlg.valideaza())
|
||||
|
||||
goT = CREATEOBJECT('Empty')
|
||||
=ADDPROPERTY(goT,'serie_act','')
|
||||
=ADDPROPERTY(goT,'nract',goDlg.nNract)
|
||||
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
|
||||
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
|
||||
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
|
||||
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
|
||||
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
|
||||
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
|
||||
=ADDPROPERTY(goT,'suma',IIF(goDlg.nSumaLei<>0,goDlg.nSumaLei,ROUND(goDlg.nSuma*goDlg.nCurs,gnPC)))
|
||||
=ADDPROPERTY(goT,'suma_val',goDlg.nSuma)
|
||||
=ADDPROPERTY(goT,'in_valuta',1)
|
||||
=ADDPROPERTY(goT,'participa_valuta',.T.)
|
||||
=ADDPROPERTY(goT,'id_valuta',goDlg.nIdValuta)
|
||||
=ADDPROPERTY(goT,'curs',goDlg.nCurs)
|
||||
=ADDPROPERTY(goT,'nume_val',ALLTRIM(NVL(goDlg.cValuta,'')))
|
||||
=ADDPROPERTY(goT,'cTipTva','F')
|
||||
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
|
||||
=ADDPROPERTY(goT,'dvi_serie','')
|
||||
=ADDPROPERTY(goT,'dvi_nract',0)
|
||||
=ADDPROPERTY(goT,'dvi_dataact',DATE())
|
||||
=ADDPROPERTY(goT,'dvi_id_fdoc',0)
|
||||
=ADDPROPERTY(goT,'dvi_fdoc','')
|
||||
=ADDPROPERTY(goT,'dvi_id_partc',0)
|
||||
=ADDPROPERTY(goT,'dvi_partc','')
|
||||
=ADDPROPERTY(goT,'dvi_scc','401')
|
||||
=ADDPROPERTY(goT,'dvi_tva_lei',0)
|
||||
=ADDPROPERTY(goT,'dvi_tva_val',0)
|
||||
=ADDPROPERTY(goT,'dvi_in_valuta',.F.)
|
||||
=ADDPROPERTY(goT,'dvi_id_valuta',0)
|
||||
=ADDPROPERTY(goT,'dvi_curs',0)
|
||||
=ADDPROPERTY(goT,'dvi_nume_val','')
|
||||
=ADDPROPERTY(goT,'dvi_valuta_proprie',0)
|
||||
=ADDPROPERTY(goT,'disc_baza_lei',ROUND(tnDiscBazaVal*tnCurs,gnPC))
|
||||
=ADDPROPERTY(goT,'disc_baza_val',tnDiscBazaVal)
|
||||
|
||||
DO DvLog WITH 'DOC ' + TRANSFORM(tnNract) + ' (' + tcValuta + '): do_adauga_factura = ' + TRANSFORM(goObj.do_adauga_factura(goT))
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaRulTemp
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp ( ;
|
||||
id_rul N(20,0), an N(4,0), luna N(2,0), cod N(20,0);
|
||||
, serie C(100), nnir N(20,0), id_articol N(10,0), denumire C(100);
|
||||
, codmat C(50), codmatf C(50), codbare C(50), um C(20);
|
||||
, id_gestiune N(5,0), nume_gestiune C(50), cgest C(20), nr_pag N(2,0);
|
||||
, gestionar C(50), comisie_receptie1 C(50), comisie_receptie2 C(50), comisie_receptie3 C(50);
|
||||
, cant N(14,3), cante N(14,3), cont C(10), acont C(20);
|
||||
, pret N(18,4), tva N(18,4), valoare N(18,4), valtva N(18,4);
|
||||
, proc_tva N(5,2), pretv N(18,4), pretvtva N(18,4), tvav N(18,4);
|
||||
, valoarev N(18,4), valtvav N(18,4), proc_tvav N(5,2), adaos N(18,4);
|
||||
, adaos_tva N(18,4), valoare_adaos N(18,4), valtva_adaos N(18,4), procent N(10,3);
|
||||
, discunitar N(18,4), discount_tva N(18,4), valoare_discount N(18,4), valtva_discount N(18,4);
|
||||
, proc_disc N(7,3), pretd N(14,4), curs N(18,4), id_valuta N(10,0);
|
||||
, nume_val C(20), id_lucrare N(20,0), nrord C(100), id_responsabil N(10,0);
|
||||
, nresp C(100), resp_marca N(18,4), dataact T, id_util N(5,0);
|
||||
, util C(30), dataora T, id_sectie N(5,0), sectie C(50);
|
||||
, csectie C(10), alcooltutun N(1,0), datain T, dataout T;
|
||||
, id_fact N(20,0), id_gestiunec N(10,0), nume_gestiunec C(50), cgestc C(20);
|
||||
, id_responsabilc N(5,0), id_reteta N(10,0), reteta C(50), nrespc C(100);
|
||||
, respc_marca N(18,4), id_set N(20,0), id_tip_rulaj N(10,0), tip_rulaj C(50);
|
||||
, id_obiect_depozit N(10,0), id_rul_aux N(10,0), nract N(20,0), serie_act C(10);
|
||||
, dataoras T, id_utils N(10,0), lot C(30), adata_expirare T;
|
||||
, id_sucursala N(5,0), sucursala C(250), id_part_rez N(10,0), part_rez C(100);
|
||||
, id_lucrare_rez N(10,0), nrord_rez C(100), subgrupa C(100), grupa C(100);
|
||||
, id_subgrupa N(5,0), id_grupa N(5,0), in_stoc N(1,0), in_crm N(1,0);
|
||||
, id_furnizor N(10,0), furnizor C(100), id_jtva_coloana N(4,0), explicatie_tva C(100);
|
||||
, taxcode N(6,0), taxname C(254), saft_procent N(18,4), codnc8 C(20);
|
||||
, id_tara_origine N(4,0), cod_tara_origine C(5), tara_origine C(50), greutate N(12,4);
|
||||
, fdoc C(30), id_fdoc N(18,4);
|
||||
, pret_lei N(18,4), pret_val N(14,4), cota_tva N(6,2))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaIntrodc
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO DvLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO DvLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DvErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO DvLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DvLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES (IIF(TYPE('gcMockAcontCrt') = 'C', gcMockAcontCrt, ''))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES ('371', '4')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (208, 'ACH. INT. 21%', 1, 0, 'RO21B', 21, 209, 1, 1, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (209, 'TVA ACH. INT. 21%', 1, 0, 'RO21T', 21, 1, 2, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 3, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 4, 301204)
|
||||
ENDPROC
|
||||
12
utile/Teste/achizitie_import/test_discount_valuta.ps1
Normal file
12
utile/Teste/achizitie_import/test_discount_valuta.ps1
Normal file
@@ -0,0 +1,12 @@
|
||||
# test_discount_valuta.ps1 - wrapper peste harness-ul generic pentru discountul financiar pe
|
||||
# factura de import in valuta (EUR/GBP) - suma/suma_val pe randurile G si T - Runda32.
|
||||
# powershell -ExecutionPolicy Bypass -File test_discount_valuta.ps1
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Teste = $PSScriptRoot
|
||||
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
|
||||
-TestPrg (Join-Path $Teste 'test_discount_valuta.prg') `
|
||||
-Steps @('doc1_eur','doc2_gbp','final') `
|
||||
-ShotsDir (Join-Path $Teste 'screenshots_discount_valuta') `
|
||||
-SyncDir (Join-Path $Teste 'uisync_discount_valuta') `
|
||||
-StepTimeoutSec 180 `
|
||||
-ReadyTimeoutSec 180
|
||||
613
utile/Teste/achizitie_import/test_dvi_bifa_valuta.prg
Normal file
613
utile/Teste/achizitie_import/test_dvi_bifa_valuta.prg
Normal file
@@ -0,0 +1,613 @@
|
||||
* test_dvi_bifa_valuta.prg
|
||||
* Runda32 (control nou chkDviInValuta, sectiunea TVA DVI): factura de import IN VALUTA (EUR)
|
||||
* cu bifa "Valuta" a DVI-ului SCOASA - DVI-ul e platit doar in lei, desi factura insasi e in
|
||||
* valuta ("factura in valuta, DVI doar in lei", cazul nou din plan).
|
||||
*
|
||||
* Verifica:
|
||||
* - la Init (factura in valuta), bifa porneste BIFATA (chkInValutaCont=1, valuta <> RON);
|
||||
* - dupa scoaterea bifei: lblDviValuta/txtDviValuta/cmdDviValuta/lblDviCurs/txtDviCurs
|
||||
* ascunse, nDviCurs=1; txtDviTvaVal ramane vizibil, comuta pe lei (nDviTvaVal recalculat, nu 0);
|
||||
* - randul T (DVI) creat de do_adauga_factura: FARA valuta/curs/suma_val (in_valuta=0,
|
||||
* id_valuta=0, curs=0, nume_val='', suma_val=0), suma = nDviTvaLei (introdus direct);
|
||||
* - valuta_proprie=1 (starea de valuta a DVI-ului difera de a facturii - factura are valuta,
|
||||
* DVI nu mai are, dupa scoaterea bifei).
|
||||
*
|
||||
* Flux REAL: dialogul `import_adauga_factura` (toDlg construit inline in programul principal,
|
||||
* capcana l - CREATEOBJECT/ADDPROPERTY nu merg dintr-o procedura in acest runtime headless).
|
||||
*
|
||||
* CAPCANA l (mock_caut_valuta.prg, confirmata si in test_e2e_dvi_ron_discount.prg): apelul REAL
|
||||
* goDlg.construieste_todlg() arunca eroarea 11 pe primul Addproperty in acest runtime headless
|
||||
* (CREATEOBJECT/ADDPROPERTY nu merg corect apelate dintr-o METODA, doar din programul PRINCIPAL) -
|
||||
* nu poate fi exercitat direct. toDlg se construieste inline in program, cu formula COPIATA
|
||||
* EXACT din ointroduceri.vc2 PROCEDURE construieste_todlg (~6157-6202, verificata in cache dupa
|
||||
* ce lane-ul de dialog a terminat Runda32):
|
||||
* lcDviVal = Iif(lDviValutaDirty, cDviValuta, cValuta) -- dvi_valuta_efectiva()
|
||||
* llDviFaraVal = (chkDviInValuta.Value=0) Or Empty(lcDviVal) Or Upper(lcDviVal)=='RON'
|
||||
* llFactFaraVal = Empty(cValuta) Or Upper(cValuta)=='RON'
|
||||
* llDviPropriu = (dvi_id_valuta_efectiva()<>nIdValuta Or dvi_curs_efectiv()<>nCurs)
|
||||
* dvi_valuta_proprie = Iif(llDviFaraVal And llFactFaraVal, 0, Iif(llDviFaraVal<>llFactFaraVal, 1, Iif(llDviPropriu,1,0)))
|
||||
* IMPORTANT: dvi_curs_efectiv()/dvi_id_valuta_efectiva() NU citesc nDviCurs/nDviIdValuta direct -
|
||||
* doar cand lDviValutaDirty/lDviCursDirty sunt adevarate (alegere explicita prin picker/curs
|
||||
* tastat). In acest test bifa e scoasa fara sa se atinga picker-ul/cursul DVI, deci flagurile
|
||||
* dirty raman .F. si valorile EFECTIVE raman cele ale facturii (nIdValuta/nCurs), NU nDviCurs=1
|
||||
* fortat de actualizeaza_stare_dvi_valuta() pe widget - acel 1 e doar pentru afisaj, nefolosit
|
||||
* de formula toDlg.
|
||||
* SCOPUL testului ramane do_adauga_factura() (crearea randului T dintr-un toDlg dat) - NU
|
||||
* verifica daca dialogul real produce chiar acest toDlg (blocat de capcana l).
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_dvi_bifa_valuta.ps1
|
||||
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_dvi_bifa_valuta_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_dvi_bifa_valuta\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO BvErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO BvLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO BvLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO BvLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnMockRaspuns, gcMockUltimMesaj, gnMockUltimTip
|
||||
gnMockRaspuns = 6
|
||||
gcMockUltimMesaj = ''
|
||||
gnMockUltimTip = 0
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (factura in EUR, curs 5) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 5)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 601)
|
||||
poAct.AddProperty('partc', 'FURNIZOR EXTERN GMBH')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: perechi reale 21% -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 220, 21, 'ACH. IMP. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 221, 21, 'TVA ACH. IMP. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp (denumire C(100), codmat C(30), cant N(14,3), pret_val N(18,4), ;
|
||||
pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), acont C(20), serie C(30), ;
|
||||
lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO BvLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F.)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO BvLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
*========================= DIALOG: factura EUR, mod TVA DVI =========================
|
||||
PUBLIC goDlg
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = 18000
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = 601
|
||||
goDlg.cPartener = 'FURNIZOR EXTERN GMBH'
|
||||
goDlg.cExplicatia = 'Import marfa, DVI fara valuta proprie'
|
||||
goDlg.nSuma = 1000
|
||||
goDlg.nSumaLei = 0
|
||||
goDlg.nCurs = 5
|
||||
goDlg.nIdValuta = 978
|
||||
goDlg.cValuta = 'EUR'
|
||||
goDlg.chkInValutaCont.Value = 1
|
||||
goDlg.chkParticipaValuta.Value = 1
|
||||
goDlg.nIdExplicatieTva = 220
|
||||
goDlg.cExplicatieTva = 'ACH. IMP. 21%'
|
||||
goDlg.nProcentTva = 21
|
||||
|
||||
goDlg.cSerieDvi = ''
|
||||
goDlg.nNractDvi = 19000
|
||||
goDlg.dDviData = DATE()
|
||||
goDlg.nIdFdocDVI = 2
|
||||
goDlg.cFelDocDvi = 'DVI'
|
||||
goDlg.nDviIdPartener = 900
|
||||
goDlg.cDviPartener = 'DIRECTIA VAMALA'
|
||||
|
||||
goDlg.optTipTva.Value = 2
|
||||
goDlg.optTipTva.InteractiveChange()
|
||||
|
||||
*========================= bifa Valuta DVI: porneste BIFATA (factura are valuta) =========================
|
||||
=Assert3('1-la Init, factura in valuta: chkDviInValuta.Value=1 (bifata)', goDlg.chkDviInValuta.Value, 1)
|
||||
=Assert3('2-la Init: txtDviValuta.Visible=1 (sectiune vizibila)', IIF(goDlg.txtDviValuta.Visible,1,0), 1)
|
||||
|
||||
*========================= scoatere bifa: sectiunea valuta DVI se ascunde, curs=1, tva val=0 =========================
|
||||
goDlg.chkDviInValuta.Value = 0
|
||||
goDlg.chkDviInValuta.InteractiveChange()
|
||||
=Assert3('3-dupa scoatere bifa: txtDviValuta.Visible=0', IIF(goDlg.txtDviValuta.Visible,1,0), 0)
|
||||
=Assert3('4-dupa scoatere bifa: cmdDviValuta.Visible=0', IIF(goDlg.cmdDviValuta.Visible,1,0), 0)
|
||||
=Assert3('5-dupa scoatere bifa: txtDviCurs.Visible=0', IIF(goDlg.txtDviCurs.Visible,1,0), 0)
|
||||
=Assert3('6-dupa scoatere bifa: txtDviTvaVal.Visible=1 (ramane vizibil, comuta pe lei)', IIF(goDlg.txtDviTvaVal.Visible,1,0), 1)
|
||||
=Assert3('7-dupa scoatere bifa: nDviCurs=1', goDlg.nDviCurs, 1)
|
||||
=Assert3('8-dupa scoatere bifa: nDviTvaVal=1050 (TVA recalculat in lei, nu 0)', goDlg.nDviTvaVal, 1050)
|
||||
|
||||
*-- TVA DVI in lei, introdusa direct (proprietate reala, ca in restul suitei - vezi
|
||||
*-- test_dvi_dialog_ui.prg scenariul F1)
|
||||
goDlg.nDviTvaLei = 900.00
|
||||
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 0, 'dialog completat, bifa Valuta DVI scoasa'
|
||||
|
||||
*========================= toDlg construit inline, do_adauga_factura REAL =========================
|
||||
*-- formula copiata exact din construieste_todlg (vezi CAPCANA l in antet) - lDviValutaDirty/
|
||||
*-- lDviCursDirty raman .F. (nu s-a atins picker-ul/cursul DVI), deci valorile efective ale
|
||||
*-- DVI-ului raman cele mostenite de la factura (nIdValuta/nCurs), nu nDviCurs=1 fortat de
|
||||
*-- actualizeaza_stare_dvi_valuta() pe widget.
|
||||
PUBLIC goT
|
||||
LOCAL lcDviValEfectiv, llDviFaraVal, llFactFaraVal, llDviPropriu, lnDviIdValutaEfectiv, lnDviCursEfectiv, llValutaProprie
|
||||
lnDviIdValutaEfectiv = IIF(goDlg.lDviValutaDirty, goDlg.nDviIdValuta, goDlg.nIdValuta)
|
||||
lnDviCursEfectiv = IIF(goDlg.lDviValutaDirty OR goDlg.lDviCursDirty, goDlg.nDviCurs, goDlg.nCurs)
|
||||
lcDviValEfectiv = IIF(goDlg.lDviValutaDirty, ALLTRIM(NVL(goDlg.cDviValuta,'')), ALLTRIM(NVL(goDlg.cValuta,'')))
|
||||
llDviFaraVal = (goDlg.chkDviInValuta.Value = 0) OR EMPTY(lcDviValEfectiv) OR UPPER(lcDviValEfectiv) == 'RON'
|
||||
llFactFaraVal = (EMPTY(goDlg.cValuta) OR UPPER(ALLTRIM(goDlg.cValuta)) == 'RON')
|
||||
llDviPropriu = (lnDviIdValutaEfectiv <> goDlg.nIdValuta OR lnDviCursEfectiv <> goDlg.nCurs)
|
||||
llValutaProprie = IIF(llDviFaraVal AND llFactFaraVal, 0, IIF(llDviFaraVal <> llFactFaraVal, 1, IIF(llDviPropriu,1,0)))
|
||||
|
||||
goT = CREATEOBJECT('Empty')
|
||||
=ADDPROPERTY(goT,'serie_act','')
|
||||
=ADDPROPERTY(goT,'nract',goDlg.nNract)
|
||||
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
|
||||
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
|
||||
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
|
||||
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
|
||||
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
|
||||
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
|
||||
=ADDPROPERTY(goT,'suma',ROUND(goDlg.nSuma*goDlg.nCurs,gnPC))
|
||||
=ADDPROPERTY(goT,'suma_val',goDlg.nSuma)
|
||||
=ADDPROPERTY(goT,'in_valuta',1)
|
||||
=ADDPROPERTY(goT,'participa_valuta',.T.)
|
||||
=ADDPROPERTY(goT,'id_valuta',goDlg.nIdValuta)
|
||||
=ADDPROPERTY(goT,'curs',goDlg.nCurs)
|
||||
=ADDPROPERTY(goT,'nume_val',ALLTRIM(NVL(goDlg.cValuta,'')))
|
||||
=ADDPROPERTY(goT,'cTipTva','D')
|
||||
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
|
||||
=ADDPROPERTY(goT,'dvi_serie',ALLTRIM(NVL(goDlg.cSerieDvi,'')))
|
||||
=ADDPROPERTY(goT,'dvi_nract',goDlg.nNractDvi)
|
||||
=ADDPROPERTY(goT,'dvi_dataact',goDlg.dDviData)
|
||||
=ADDPROPERTY(goT,'dvi_id_fdoc',goDlg.nIdFdocDVI)
|
||||
=ADDPROPERTY(goT,'dvi_fdoc',goDlg.cFelDocDvi)
|
||||
=ADDPROPERTY(goT,'dvi_id_partc',goDlg.nDviIdPartener)
|
||||
=ADDPROPERTY(goT,'dvi_partc',goDlg.cDviPartener)
|
||||
=ADDPROPERTY(goT,'dvi_scc','401')
|
||||
=ADDPROPERTY(goT,'dvi_tva_lei',goDlg.nDviTvaLei)
|
||||
=ADDPROPERTY(goT,'dvi_tva_val',goDlg.nDviTvaVal)
|
||||
*-- bifa scoasa => dvi_in_valuta=.F. (llDviFaraVal), indiferent de valuta efectiva mostenita
|
||||
=ADDPROPERTY(goT,'dvi_in_valuta',!llDviFaraVal)
|
||||
=ADDPROPERTY(goT,'dvi_id_valuta',lnDviIdValutaEfectiv)
|
||||
=ADDPROPERTY(goT,'dvi_curs',lnDviCursEfectiv)
|
||||
=ADDPROPERTY(goT,'dvi_nume_val',lcDviValEfectiv)
|
||||
=ADDPROPERTY(goT,'dvi_valuta_proprie',llValutaProprie)
|
||||
=ADDPROPERTY(goT,'disc_baza_lei',0)
|
||||
=ADDPROPERTY(goT,'disc_baza_val',0)
|
||||
|
||||
LOCAL llOkAdauga
|
||||
llOkAdauga = goObj.do_adauga_factura(goT)
|
||||
=Assert3('9-do_adauga_factura(goT) reuseste', IIF(llOkAdauga,1,0), 1)
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 1, 'document creat, dupa Termin'
|
||||
|
||||
*========================= randul T (DVI): fara valuta/curs/suma_val =========================
|
||||
SELECT introdc
|
||||
SET ORDER TO
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('10-randul T-DVI (rand_dvi=1) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('11-T-DVI.suma=900.00 (nDviTvaLei introdus)', suma, 900.00)
|
||||
=Assert3('12-T-DVI.suma_val=0 (fara valuta)', NVL(suma_val,0), 0)
|
||||
=Assert3('13-T-DVI.in_valuta=0', NVL(in_valuta,0), 0)
|
||||
=Assert3('14-T-DVI.id_valuta=0', NVL(id_valuta,0), 0)
|
||||
=Assert3('15-T-DVI.curs=0', NVL(curs,0), 0)
|
||||
=AssertStr('16-T-DVI.nume_val=""', ALLTRIM(NVL(nume_val,'?')), '')
|
||||
=Assert3('17-T-DVI.valuta_proprie=1 (factura are valuta, DVI nu mai are)', NVL(valuta_proprie,0), 1)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 7
|
||||
DO BvLog WITH ' FAIL 11-17: T-DVI negasit'
|
||||
ENDIF
|
||||
|
||||
*-- randul B (baza facturii) ramane in valuta - discountul/bifa DVI nu-l afecteaza
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 18000 AND tip_rand == 'B'
|
||||
=Assert3('18-randul B (baza) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('19-B.in_valuta=1 (factura ramane in valuta)', NVL(in_valuta,0), 1)
|
||||
=Assert3('20-B.suma_val=1000.00', NVL(suma_val,0), 1000.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO BvLog WITH ' FAIL 19-20: B negasit'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 2, 'randul T-DVI fara valuta verificat - vezi log'
|
||||
|
||||
DO BvLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO BvLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO BvLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 3, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO BvLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE CreeazaIntrodc
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO BvLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO BvLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE AssertStr
|
||||
LPARAMETERS tcLabel, tcActual, tcExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF tcActual == tcExpected
|
||||
pnPass = pnPass + 1
|
||||
DO BvLog WITH ' PASS ' + tcLabel + ' (=[' + tcActual + '])'
|
||||
ELSE
|
||||
DO BvLog WITH ' FAIL ' + tcLabel + ' (actual=[' + tcActual + '] asteptat=[' + tcExpected + '])'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE BvErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO BvLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE BvLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES ('')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VCONFIG_CONT_IREG' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (contpart C(10), fel_cont N(1), cu_inregistrari N(1), ;
|
||||
explic_cont C(100), exceptie C(10), pozitie N(1), invers N(1), gasit N(1))
|
||||
INSERT INTO (m.tcCursor) VALUES ('401', 0, 0, 'Furnizori', '', 0, 0, 0)
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 1, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 2, 301204)
|
||||
ENDPROC
|
||||
12
utile/Teste/achizitie_import/test_dvi_bifa_valuta.ps1
Normal file
12
utile/Teste/achizitie_import/test_dvi_bifa_valuta.ps1
Normal file
@@ -0,0 +1,12 @@
|
||||
# test_dvi_bifa_valuta.ps1 - wrapper peste harness-ul generic pentru bifa noua "Valuta" din
|
||||
# sectiunea TVA DVI (chkDviInValuta) - Runda32.
|
||||
# powershell -ExecutionPolicy Bypass -File test_dvi_bifa_valuta.ps1
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Teste = $PSScriptRoot
|
||||
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
|
||||
-TestPrg (Join-Path $Teste 'test_dvi_bifa_valuta.prg') `
|
||||
-Steps @('dialog_bifa_scoasa','document_creat','rand_t_dvi_verificat','final') `
|
||||
-ShotsDir (Join-Path $Teste 'screenshots_dvi_bifa_valuta') `
|
||||
-SyncDir (Join-Path $Teste 'uisync_dvi_bifa_valuta') `
|
||||
-StepTimeoutSec 180 `
|
||||
-ReadyTimeoutSec 180
|
||||
794
utile/Teste/achizitie_import/test_dvi_dialog_ui.prg
Normal file
794
utile/Teste/achizitie_import/test_dvi_dialog_ui.prg
Normal file
@@ -0,0 +1,794 @@
|
||||
* test_dvi_dialog_ui.prg
|
||||
* Runda30 (F1, plan fizzy-imagining-parnas.md): teste UI pe formularul REAL de adaugare
|
||||
* factura (import_adauga_factura, COMUN\clase\ointroduceri.vcx), clona a test_adauga_factura_ui.prg,
|
||||
* focalizata pe comportamentul dialogului pentru blocul DVI (valuta/curs proprii) si discount:
|
||||
* 1. precompletarea valutei/cursului DVI din factura la Init (mirror automat);
|
||||
* 2. contractul nou al mock_caut_valuta (goMockValutaCoada, coada FIFO) exercitat prin
|
||||
* 2 pick-uri diferite in acelasi flux (valuta facturii, apoi valuta DVI) + fallback
|
||||
* la contractul vechi (goMockValuta) cand coada se goleste;
|
||||
* 3. alegerea RON pe DVI (curs fix 1, curs disabled, TVA valuta ascunsa si 0);
|
||||
* 4. garda de dirty: TVA in valuta DVI editat manual (txtDviTvaVal.Valid) nu mai e
|
||||
* rescris de recalc_tva (cazul unei a treia valute, diferita de RON si de factura);
|
||||
* 5. Runda32: discountul e activ direct pe nDiscBaza<>0 (fara chkAreDiscount); caption-ul
|
||||
* txtDiscBaza urmeaza valuta facturii, txtDiscBaza e permanent vizibil;
|
||||
* 6. dirty-flags: txtDviCurs.Valid seteaza dirty; realegerea valutei DVI reseteaza cursul;
|
||||
* 7. validari blocante: DVI non-RON cu curs 0; discount negativ; discount >= suma facturii.
|
||||
*
|
||||
* ASUMPTII (de confruntat cu implementarea reala):
|
||||
* - proprietatile de dialog se numesc nDviIdValuta, cDviValuta, nDviCurs, lDviCursDirty,
|
||||
* lDviTvaValDirty, nDiscBaza (verificate pe ointroduceri.vc2, lane F1+F2 dialog,
|
||||
* 27.07.2026; Runda32 elimina chkAreDiscount/txtDiscTva/nDiscTva/lDiscTvaDirty);
|
||||
* - RON e o valuta cu id propriu (1), nu id_valuta=0 (vezi test_repro_valuta_dblclick.prg);
|
||||
* picker-ul (cmdValuta/cmdDviValuta.Click) ignora rezultate cu id_valuta=0 (guard
|
||||
* !Empty(Nvl(loCauta.id_valuta,0))).
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_dvi_dialog_ui.ps1
|
||||
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_dvi_dialog_ui_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_dvi_dialog\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO DdErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO DdLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO DdLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO DdLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnMockRaspuns, gcMockUltimMesaj, gnMockUltimTip
|
||||
gnMockRaspuns = 6
|
||||
gcMockUltimMesaj = ''
|
||||
gnMockUltimTip = 0
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (factura in EUR, curs 5 - ca DVI-ul sa aiba ce mosteni la Init) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 5)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 501)
|
||||
poAct.AddProperty('partc', 'FURNIZOR EXTERN GMBH')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: perechi reale 21% (achizitii interne + import) -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 208, 'ACH. INT. 21%', 1, 0, 1, 'RO21B', 'RO21T', 21, 209)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 209, 'TVA ACH. INT. 21%', 1, 0, 1, 'RO21T', '', 21, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (3, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (4, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 208, 21, 'ACH. INT. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 209, 21, 'TVA ACH. INT. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp (denumire C(100), codmat C(30), cant N(14,3), pret_val N(18,4), ;
|
||||
pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), acont C(20), serie C(30), ;
|
||||
lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
*-- index ord_doc INAINTE de CREATEOBJECT (capcana p, docs/testare-ui-vfp.md)
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO DdLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F. - mod import)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO DdLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
DO HarnessStep WITH 0, 'nota goala afisata, mod import (.F.)'
|
||||
|
||||
*========================= SCENARIU G: coada FIFO a mock-ului, 2 pick-uri in acelasi flux =========================
|
||||
*-- valuta facturii (GBP) apoi valuta DVI (CHF) - independente; dupa coada, fallback la
|
||||
*-- contractul vechi (goMockValuta fix).
|
||||
PUBLIC goDlg
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = 6001
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = 601
|
||||
goDlg.cPartener = 'FURNIZOR UK LTD'
|
||||
goDlg.nSuma = 100
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PUBLIC goMockValuta, goMockValutaCoada
|
||||
goMockValuta = CREATEOBJECT('Custom')
|
||||
goMockValuta.AddProperty('id_valuta', 978)
|
||||
goMockValuta.AddProperty('nume_val', 'EUR')
|
||||
goMockValutaCoada = CREATEOBJECT('Collection')
|
||||
LOCAL loValGbp, loValChf
|
||||
loValGbp = CREATEOBJECT('Custom')
|
||||
loValGbp.AddProperty('id_valuta', 826)
|
||||
loValGbp.AddProperty('nume_val', 'GBP')
|
||||
goMockValutaCoada.Add(loValGbp)
|
||||
loValChf = CREATEOBJECT('Custom')
|
||||
loValChf.AddProperty('id_valuta', 756)
|
||||
loValChf.AddProperty('nume_val', 'CHF')
|
||||
goMockValutaCoada.Add(loValChf)
|
||||
|
||||
goDlg.cmdValuta.Click()
|
||||
=Assert3('G1-pick1 (valuta facturii) seteaza nIdValuta=826 (GBP)', goDlg.nIdValuta, 826)
|
||||
=AssertStr('G2-pick1 cValuta=GBP', ALLTRIM(goDlg.cValuta), 'GBP')
|
||||
=Assert3('G3-DVI mirror dupa pick1 (nDviIdValuta=826, nu e dirty inca)', goDlg.nDviIdValuta, 826)
|
||||
|
||||
goDlg.cmdDviValuta.Click()
|
||||
=Assert3('G4-pick2 (valuta DVI) seteaza nDviIdValuta=756 (CHF)', goDlg.nDviIdValuta, 756)
|
||||
=AssertStr('G5-pick2 cDviValuta=CHF', ALLTRIM(goDlg.cDviValuta), 'CHF')
|
||||
=Assert3('G6-valuta facturii ramane GBP (independenta de pick2)', goDlg.nIdValuta, 826)
|
||||
=Assert3('G7-coada goala dupa 2 pick-uri (Count=0)', goMockValutaCoada.Count, 0)
|
||||
|
||||
LOCAL loFallback
|
||||
loFallback = caut_valuta()
|
||||
=Assert3('G8-coada goala: caut_valuta() revine la contractul vechi (goMockValuta EUR=978)', loFallback.id_valuta, 978)
|
||||
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 1, 'scenariul G (coada FIFO mock_caut_valuta) verificat - vezi log'
|
||||
|
||||
*========================= SCENARIU A: precompletare valuta/curs DVI din factura la Init =========================
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
=Assert3('A1-precompletare nDviIdValuta=978 (EUR, ca factura) la Init', goDlg.nDviIdValuta, 978)
|
||||
=AssertStr('A2-precompletare cDviValuta=EUR la Init', ALLTRIM(goDlg.cDviValuta), 'EUR')
|
||||
=Assert3('A3-precompletare nDviCurs=5 (ca factura) la Init', goDlg.nDviCurs, 5)
|
||||
|
||||
goDlg.optTipTva.Value = 2
|
||||
goDlg.optTipTva.InteractiveChange()
|
||||
=Assert3('A4-txtDviValuta.Visible=1 in mod TVA DVI', IIF(goDlg.txtDviValuta.Visible,1,0), 1)
|
||||
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 2, 'scenariul A (precompletare DVI la Init) verificat - vezi log'
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
|
||||
*========================= SCENARIU B: alegerea RON pe DVI =========================
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.optTipTva.Value = 2
|
||||
goDlg.optTipTva.InteractiveChange()
|
||||
|
||||
PUBLIC goMockValutaCoada
|
||||
goMockValutaCoada = CREATEOBJECT('Collection')
|
||||
LOCAL loValRon
|
||||
loValRon = CREATEOBJECT('Custom')
|
||||
loValRon.AddProperty('id_valuta', 1)
|
||||
loValRon.AddProperty('nume_val', 'RON')
|
||||
goMockValutaCoada.Add(loValRon)
|
||||
|
||||
goDlg.cmdDviValuta.Click()
|
||||
=Assert3('B1-alegere RON: nDviIdValuta=1', goDlg.nDviIdValuta, 1)
|
||||
=AssertStr('B2-alegere RON: cDviValuta=RON', ALLTRIM(goDlg.cDviValuta), 'RON')
|
||||
=Assert3('B3-alegere RON: nDviCurs fixat la 1', goDlg.nDviCurs, 1)
|
||||
=Assert3('B4-alegere RON: txtDviCurs.Enabled=0 (disabled)', IIF(goDlg.txtDviCurs.Enabled,1,0), 0)
|
||||
=Assert3('B5-alegere RON: txtDviTvaVal.Visible=1 (ramane vizibil, comuta pe lei)', IIF(goDlg.txtDviTvaVal.Visible,1,0), 1)
|
||||
=Assert3('B6-alegere RON: nDviTvaVal=0', goDlg.nDviTvaVal, 0)
|
||||
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 3, 'scenariul B (RON pe DVI) verificat - vezi log'
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
|
||||
*========================= SCENARIU C: garda de dirty pe TVA in valuta DVI (a treia valuta) =========================
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.chkInValutaCont.Value = 1
|
||||
goDlg.nSuma = 1000
|
||||
goDlg.nProcentTva = 21
|
||||
goDlg.optTipTva.Value = 2
|
||||
goDlg.optTipTva.InteractiveChange()
|
||||
|
||||
PUBLIC goMockValutaCoada
|
||||
goMockValutaCoada = CREATEOBJECT('Collection')
|
||||
LOCAL loValUsd
|
||||
loValUsd = CREATEOBJECT('Custom')
|
||||
loValUsd.AddProperty('id_valuta', 840)
|
||||
loValUsd.AddProperty('nume_val', 'USD')
|
||||
goMockValutaCoada.Add(loValUsd)
|
||||
goDlg.cmdDviValuta.Click()
|
||||
=AssertStr('C1-DVI in USD (a treia valuta, diferita de EUR factura)', ALLTRIM(goDlg.cDviValuta), 'USD')
|
||||
|
||||
goDlg.txtDviCurs.Value = 4.5
|
||||
goDlg.txtDviCurs.Valid()
|
||||
goDlg.recalc_tva()
|
||||
*-- nSumaLei=1000*5=5000; TvaLei=5000*21%=1050; TvaVal(auto)=Round(1050/4.5,2)=233.33
|
||||
=Assert3('C2-baseline auto nDviTvaVal=233.33 (1050/4.5)', goDlg.nDviTvaVal, 233.33)
|
||||
|
||||
goDlg.txtDviTvaVal.Value = 999.99
|
||||
goDlg.txtDviTvaVal.Valid()
|
||||
=Assert3('C3-dupa editare manuala, nDviTvaVal=999.99', goDlg.nDviTvaVal, 999.99)
|
||||
=Assert3('C4-lDviTvaValDirty=1 dupa editare manuala', IIF(goDlg.lDviTvaValDirty,1,0), 1)
|
||||
|
||||
goDlg.recalc_tva()
|
||||
=Assert3('C5-dupa recalc_tva() repetat, nDviTvaVal ramane manual (999.99, nu se rescrie)', goDlg.nDviTvaVal, 999.99)
|
||||
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 4, 'scenariul C (garda dirty TVA valuta DVI) verificat - vezi log'
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
|
||||
*========================= SCENARIU D: discount fara bifa (Runda32), caption dupa valuta =========================
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
=Assert3('D1-txtDiscBaza.Visible=1 permanent (fara chkAreDiscount)', IIF(goDlg.txtDiscBaza.Visible,1,0), 1)
|
||||
=AssertContains('D2-caption txtDiscBaza urmeaza valuta facturii (EUR)', 'EUR', goDlg.lblDiscBaza.Caption)
|
||||
|
||||
goDlg.chkInValutaCont.Value = 0
|
||||
goDlg.chkInValutaCont.InteractiveChange()
|
||||
=AssertContains('D3-caption dupa scoaterea valutei: "RON"', 'RON', goDlg.lblDiscBaza.Caption)
|
||||
|
||||
goDlg.txtDiscBaza.Value = 500
|
||||
goDlg.txtDiscBaza.Valid()
|
||||
=Assert3('D4-nDiscBaza=500 dupa completare', goDlg.nDiscBaza, 500)
|
||||
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 5, 'scenariul D (discount fara bifa, caption dupa valuta) verificat - vezi log'
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
|
||||
*========================= SCENARIU E: dirty-flags txtDviCurs + revert la realegere valuta DVI =========================
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.optTipTva.Value = 2
|
||||
goDlg.optTipTva.InteractiveChange()
|
||||
|
||||
goDlg.txtDviCurs.Value = 4.75
|
||||
goDlg.txtDviCurs.Valid()
|
||||
=Assert3('E1-lDviCursDirty=1 dupa editare manuala curs DVI', IIF(goDlg.lDviCursDirty,1,0), 1)
|
||||
=Assert3('E2-nDviCurs=4.75 dupa editare manuala', goDlg.nDviCurs, 4.75)
|
||||
|
||||
PUBLIC goMockValutaCoada
|
||||
goMockValutaCoada = CREATEOBJECT('Collection')
|
||||
LOCAL loValEur2
|
||||
loValEur2 = CREATEOBJECT('Custom')
|
||||
loValEur2.AddProperty('id_valuta', 978)
|
||||
loValEur2.AddProperty('nume_val', 'EUR')
|
||||
goMockValutaCoada.Add(loValEur2)
|
||||
goDlg.cmdDviValuta.Click()
|
||||
=Assert3('E3-lDviCursDirty resetat (0) dupa realegerea valutei DVI', IIF(goDlg.lDviCursDirty,1,0), 0)
|
||||
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 6, 'scenariul E (dirty-flags txtDviCurs + revert) verificat - vezi log'
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
|
||||
*========================= SCENARIU F1: validare blocanta - DVI non-RON cu curs 0 =========================
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = 6002
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = 601
|
||||
goDlg.cPartener = 'FURNIZOR UK LTD'
|
||||
goDlg.nSuma = 100
|
||||
goDlg.optTipTva.Value = 2
|
||||
goDlg.optTipTva.InteractiveChange()
|
||||
goDlg.nNractDvi = 7002
|
||||
goDlg.dDviData = DATE()
|
||||
goDlg.nDviIdPartener = 900
|
||||
goDlg.cDviPartener = 'DIRECTIA VAMALA'
|
||||
goDlg.nDviTvaLei = 21
|
||||
goDlg.nDviIdValuta = 840
|
||||
goDlg.cDviValuta = 'USD'
|
||||
goDlg.nDviCurs = 0
|
||||
*-- flagurile dirty marcheaza ca DVI a fost ales explicit (picker/curs tastat) - fara ele,
|
||||
*-- dvi_valuta_efectiva()/dvi_curs_efectiv() urmeaza factura (EUR), nu USD/0 setate direct
|
||||
goDlg.lDviValutaDirty = .T.
|
||||
goDlg.lDviCursDirty = .T.
|
||||
|
||||
gcMockUltimMesaj = ''
|
||||
LOCAL llOkF1
|
||||
llOkF1 = goDlg.valideaza()
|
||||
=Assert3('F1a-valideaza() respinge DVI non-RON cu curs 0', IIF(llOkF1,1,0), 0)
|
||||
=AssertContains('F1b-mesaj contine "curs"', 'curs', gcMockUltimMesaj)
|
||||
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 7, 'scenariul F1 (DVI curs 0 blocant) verificat - vezi log'
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
|
||||
*========================= SCENARIU F2: validari blocante - discount negativ / discount >= suma =========================
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = 6003
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = 601
|
||||
goDlg.cPartener = 'FURNIZOR UK LTD'
|
||||
goDlg.nSuma = 100
|
||||
goDlg.nIdExplicatieTva = 208
|
||||
goDlg.cExplicatieTva = 'ACH. INT. 21%'
|
||||
goDlg.optTipTva.Value = 1
|
||||
goDlg.txtDiscBaza.Value = -10
|
||||
goDlg.txtDiscBaza.Valid()
|
||||
|
||||
gcMockUltimMesaj = ''
|
||||
LOCAL llOkF2a
|
||||
llOkF2a = goDlg.valideaza()
|
||||
=Assert3('F2a-valideaza() respinge discount negativ', IIF(llOkF2a,1,0), 0)
|
||||
=AssertContains('F2b-mesaj contine "discount"', 'discount', gcMockUltimMesaj)
|
||||
|
||||
goDlg.txtDiscBaza.Value = 100
|
||||
goDlg.txtDiscBaza.Valid()
|
||||
gcMockUltimMesaj = ''
|
||||
LOCAL llOkF2c
|
||||
llOkF2c = goDlg.valideaza()
|
||||
=Assert3('F2c-valideaza() respinge discount >= suma facturii', IIF(llOkF2c,1,0), 0)
|
||||
=AssertContains('F2d-mesaj contine "discount"', 'discount', gcMockUltimMesaj)
|
||||
|
||||
goDlg.txtDiscBaza.Value = 50
|
||||
goDlg.txtDiscBaza.Valid()
|
||||
LOCAL llOkF2e
|
||||
llOkF2e = goDlg.valideaza()
|
||||
=Assert3('F2e-discount < suma: valideaza() trece', IIF(llOkF2e,1,0), 1)
|
||||
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 8, 'scenariul F2 (discount negativ / >=suma blocante) verificat - vezi log'
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
|
||||
*========================= SCENARIU H: regresie - Tab fara modificare NU inghenuncheaza dirty =========================
|
||||
*-- Regresia reala reparata de orchestrator: garda veche (This.Value<>Thisform.nXxx) nu se
|
||||
*-- declansa NICIODATA, nici in productie, pentru ca ControlSource sincronizeaza proprietatea
|
||||
*-- legata INAINTE ca Valid sa apuce sa compare. Fix: tipar nOldVal (GotFocus retine valoarea
|
||||
*-- la intrare, Valid seteaza dirty doar daca s-a schimbat fata de acel moment - cf.
|
||||
*-- GridArt.cCant.Text1.GotFocus, deja existent in proiect). Fara acest test, un refactor
|
||||
*-- viitor ar putea reintroduce garda veche (mereu "dirty", declansata de intamplare de
|
||||
*-- initializarea la 0 a lui nOldVal) fara sa aprinda nimic.
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = 6004
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = 601
|
||||
goDlg.cPartener = 'FURNIZOR UK LTD'
|
||||
goDlg.nSuma = 100
|
||||
goDlg.optTipTva.Value = 2
|
||||
goDlg.optTipTva.InteractiveChange()
|
||||
|
||||
*-- txtDviTvaVal: valoare initiala, dirty resetat, Tab FARA modificare, apoi modificare reala
|
||||
goDlg.lDviTvaValDirty = .F.
|
||||
goDlg.txtDviTvaVal.Value = 500
|
||||
goDlg.txtDviTvaVal.GotFocus()
|
||||
goDlg.txtDviTvaVal.Valid()
|
||||
=Assert3('H1-txtDviTvaVal: Tab fara modificare NU seteaza dirty', IIF(goDlg.lDviTvaValDirty,1,0), 0)
|
||||
goDlg.txtDviTvaVal.Value = 777
|
||||
goDlg.txtDviTvaVal.Valid()
|
||||
=Assert3('H2-txtDviTvaVal: modificare reala SETEAZA dirty', IIF(goDlg.lDviTvaValDirty,1,0), 1)
|
||||
|
||||
*-- txtDviCurs: acelasi tipar
|
||||
goDlg.lDviCursDirty = .F.
|
||||
goDlg.txtDviCurs.Value = 5
|
||||
goDlg.txtDviCurs.GotFocus()
|
||||
goDlg.txtDviCurs.Valid()
|
||||
=Assert3('H3-txtDviCurs: Tab fara modificare NU seteaza dirty', IIF(goDlg.lDviCursDirty,1,0), 0)
|
||||
goDlg.txtDviCurs.Value = 6
|
||||
goDlg.txtDviCurs.Valid()
|
||||
=Assert3('H4-txtDviCurs: modificare reala SETEAZA dirty', IIF(goDlg.lDviCursDirty,1,0), 1)
|
||||
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 9, 'scenariul H (Tab fara modificare nu seteaza dirty) verificat - vezi log'
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
|
||||
DO DdLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO DdLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO DdLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 10, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO DdLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE CreeazaIntrodc
|
||||
*-- Runda30 (F1/pas2): coloane NOI rand_dvi N(1), valuta_proprie N(1) fata de structura veche.
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
FUNCTION RECCOUNT_ACTIVE
|
||||
LPARAMETERS tcAlias
|
||||
LOCAL lnSel, lnCnt
|
||||
lnSel = SELECT()
|
||||
SELECT (tcAlias)
|
||||
COUNT TO lnCnt FOR !DELETED()
|
||||
SELECT (lnSel)
|
||||
RETURN lnCnt
|
||||
ENDFUNC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO DdLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO DdLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE AssertStr
|
||||
LPARAMETERS tcLabel, tcActual, tcExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF tcActual == tcExpected
|
||||
pnPass = pnPass + 1
|
||||
DO DdLog WITH ' PASS ' + tcLabel + ' (=[' + tcActual + '])'
|
||||
ELSE
|
||||
DO DdLog WITH ' FAIL ' + tcLabel + ' (actual=[' + tcActual + '] asteptat=[' + tcExpected + '])'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE AssertContains
|
||||
LPARAMETERS tcLabel, tcNeedle, tcHaystack
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF UPPER(ALLTRIM(tcNeedle)) $ UPPER(ALLTRIM(NVL(tcHaystack,'')))
|
||||
pnPass = pnPass + 1
|
||||
DO DdLog WITH ' PASS ' + tcLabel + ' ([' + tcNeedle + '] gasit in [' + tcHaystack + '])'
|
||||
ELSE
|
||||
DO DdLog WITH ' FAIL ' + tcLabel + ' ([' + tcNeedle + '] NEGASIT in [' + tcHaystack + '])'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DdErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO DdLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DdLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES (IIF(TYPE('gcMockAcontCrt') = 'C', gcMockAcontCrt, ''))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES ('371', '4')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (208, 'ACH. INT. 21%', 1, 0, 'RO21B', 21, 209, 1, 1, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (209, 'TVA ACH. INT. 21%', 1, 0, 'RO21T', 21, 1, 2, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 3, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 4, 301204)
|
||||
ENDPROC
|
||||
11
utile/Teste/achizitie_import/test_dvi_dialog_ui.ps1
Normal file
11
utile/Teste/achizitie_import/test_dvi_dialog_ui.ps1
Normal file
@@ -0,0 +1,11 @@
|
||||
# test_dvi_dialog_ui.ps1 - wrapper peste harness-ul generic pentru testul dialogului DVI/discount.
|
||||
# Rulare: powershell -ExecutionPolicy Bypass -File test_dvi_dialog_ui.ps1
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Teste = $PSScriptRoot
|
||||
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
|
||||
-TestPrg (Join-Path $Teste 'test_dvi_dialog_ui.prg') `
|
||||
-Steps @('nota_goala','coada_fifo_mock','precompletare_dvi','ron_pe_dvi','garda_dirty_tva_dvi','discount_fara_bifa','dirty_curs_dvi','f1_dvi_curs_zero','f2_discount_negativ_sau_max','tab_fara_modificare','final') `
|
||||
-ShotsDir (Join-Path $Teste 'screenshots_dvi_dialog') `
|
||||
-SyncDir (Join-Path $Teste 'uisync_dvi_dialog') `
|
||||
-StepTimeoutSec 180 `
|
||||
-ReadyTimeoutSec 180
|
||||
718
utile/Teste/achizitie_import/test_dvi_multicota.prg
Normal file
718
utile/Teste/achizitie_import/test_dvi_multicota.prg
Normal file
@@ -0,0 +1,718 @@
|
||||
* test_dvi_multicota.prg
|
||||
* Scenariul raportat de Marius (28.07.2026): factura de import in EUR cu discount financiar,
|
||||
* TVA-ul platit in vama (DVI) in RON si articole pe DOUA cote (21% si 11%). Verifica pe fluxul
|
||||
* REAL (dialog import_adauga_factura + do_adauga_articol + sincronizeaza) ca toate cele trei
|
||||
* familii de randuri ale documentului ajung pe cotele articolelor, concordant:
|
||||
* - S (baza): cate un rand pe cont+cota, cu ptva-ul articolelor lui (creeaza_rand_s + tnCota);
|
||||
* - G (discount): spart proportional cu bazele pe cota (sparge_discount), total pastrat;
|
||||
* - T (TVA DVI, rand protejat valuta_proprie=1): spart pe cote cu pondere baza x cota
|
||||
* (sparge_tva_protejat), total pastrat = suma tastata de pe DVI.
|
||||
*
|
||||
* Cifre: 1500 EUR (1000@21% + 500@11%), curs 5, discount 150 EUR (10%), TVA DVI 1192.50 lei
|
||||
* (= TVA-ul corect pe baze diminuate: (1000-100)*21% + (500-50)*11% = 238.50 EUR x 5).
|
||||
* - G: 100 EUR (500 lei) pe 21% + 50 EUR (250 lei) pe 11%
|
||||
* - T: 1192.50 * 210/265 = 945.00 lei pe 21% + 1192.50 * 55/265 = 247.50 lei pe 11%
|
||||
* (ponderi: 1000*21% = 210, 500*11% = 55), suma_val = 0 pe ambele (DVI in RON).
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_dvi_multicota.ps1
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_dvi_multicota_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_dvi_multicota\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO McErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO McLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO McLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_cauta_nom_articole.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO McLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
PUBLIC goMockValuta
|
||||
goMockValuta = CREATEOBJECT('Custom')
|
||||
goMockValuta.AddProperty('id_valuta', 978)
|
||||
goMockValuta.AddProperty('nume_val', 'EUR')
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnButon
|
||||
STORE 2 TO gnButon
|
||||
PUBLIC gcMockArtCodmat, gcMockAcontCrt
|
||||
gcMockArtCodmat = ''
|
||||
gcMockAcontCrt = ''
|
||||
PUBLIC gnMockRaspuns
|
||||
gnMockRaspuns = 6
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (moneda principala EUR, curs 5) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 5)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 601)
|
||||
poAct.AddProperty('partc', 'MULTI SUPPLY SRL')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: DOUA familii import (FO), 21% si 11% -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (3, 222, 'ACH. IMP. 11%', 1, 0, 1, 'FO11B', 'FO11T', 11, 223)
|
||||
INSERT INTO jtva_coloane2 VALUES (4, 223, 'TVA ACH. IMP. 11%', 1, 0, 1, 'FO11T', '', 11, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301205-Import de bunuri cota 11%', 301205, '', 11, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 220, 21, 'ACH. IMP. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 221, 21, 'TVA ACH. IMP. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
DO CreeazaRulTemp
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO McLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F.)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO McLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
*========================= FACTURA: 1500 EUR (1000@21% + 500@11%), discount 150 EUR =========================
|
||||
PUBLIC goDlg, goT, gcDocKey1
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = 17000
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = 601
|
||||
goDlg.cPartener = 'MULTI SUPPLY SRL'
|
||||
goDlg.cExplicatia = 'Import marfa multicota'
|
||||
goDlg.nSuma = 1500
|
||||
goDlg.nSumaLei = 0
|
||||
goDlg.nCurs = 5
|
||||
goDlg.nIdValuta = 978
|
||||
goDlg.cValuta = 'EUR'
|
||||
goDlg.nIdExplicatieTva = 220
|
||||
goDlg.cExplicatieTva = 'ACH. IMP. 21%'
|
||||
goDlg.optTipTva.Value = 2
|
||||
goDlg.chkInValutaCont.Value = 1
|
||||
goDlg.chkParticipaValuta.Value = 1
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO McLog WITH 'valideaza = ' + TRANSFORM(goDlg.valideaza())
|
||||
|
||||
goT = CREATEOBJECT('Empty')
|
||||
=ADDPROPERTY(goT,'serie_act','')
|
||||
=ADDPROPERTY(goT,'nract',goDlg.nNract)
|
||||
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
|
||||
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
|
||||
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
|
||||
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
|
||||
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
|
||||
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
|
||||
=ADDPROPERTY(goT,'suma',ROUND(goDlg.nSuma*goDlg.nCurs,gnPC))
|
||||
=ADDPROPERTY(goT,'suma_val',goDlg.nSuma)
|
||||
=ADDPROPERTY(goT,'in_valuta',goDlg.chkInValutaCont.Value)
|
||||
=ADDPROPERTY(goT,'participa_valuta',.T.)
|
||||
=ADDPROPERTY(goT,'id_valuta',goDlg.nIdValuta)
|
||||
=ADDPROPERTY(goT,'curs',goDlg.nCurs)
|
||||
=ADDPROPERTY(goT,'nume_val',ALLTRIM(NVL(goDlg.cValuta,'')))
|
||||
=ADDPROPERTY(goT,'cTipTva','D')
|
||||
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
|
||||
=ADDPROPERTY(goT,'dvi_serie','')
|
||||
=ADDPROPERTY(goT,'dvi_nract',9017)
|
||||
=ADDPROPERTY(goT,'dvi_dataact',DATE())
|
||||
=ADDPROPERTY(goT,'dvi_id_fdoc',2)
|
||||
=ADDPROPERTY(goT,'dvi_fdoc','DVI')
|
||||
=ADDPROPERTY(goT,'dvi_id_partc',901)
|
||||
=ADDPROPERTY(goT,'dvi_partc','DIRECTIA VAMALA')
|
||||
=ADDPROPERTY(goT,'dvi_scc','401')
|
||||
=ADDPROPERTY(goT,'dvi_tva_lei',1192.50)
|
||||
=ADDPROPERTY(goT,'dvi_tva_val',0)
|
||||
=ADDPROPERTY(goT,'dvi_in_valuta',.F.)
|
||||
=ADDPROPERTY(goT,'dvi_id_valuta',0)
|
||||
=ADDPROPERTY(goT,'dvi_curs',0)
|
||||
=ADDPROPERTY(goT,'dvi_nume_val','')
|
||||
=ADDPROPERTY(goT,'dvi_valuta_proprie',1)
|
||||
=ADDPROPERTY(goT,'disc_baza_lei',ROUND(150*5,gnPC))
|
||||
=ADDPROPERTY(goT,'disc_baza_val',150)
|
||||
|
||||
LOCAL llOkAdauga
|
||||
llOkAdauga = goObj.do_adauga_factura(goT)
|
||||
=Assert3('1-do_adauga_factura(goT) reuseste', IIF(llOkAdauga,1,0), 1)
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT introdc
|
||||
SET ORDER TO
|
||||
LOCATE FOR nract = 17000 AND tip_rand == 'B'
|
||||
IF FOUND()
|
||||
gcDocKey1 = ALLTRIM(NVL(doc_key,''))
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO HarnessStep WITH 0, 'factura creata, doc_key=' + gcDocKey1
|
||||
|
||||
*========================= DOUA ARTICOLE, COTE DIFERITE (21% si 11%) =========================
|
||||
gcMockArtCodmat = 'ART-BULD-212'
|
||||
gcMockAcontCrt = ''
|
||||
TRY
|
||||
goObj.do_adauga_articol()
|
||||
CATCH TO loExcA1
|
||||
DO McLog WITH 'EROARE do_adauga_articol (1) ' + TRANSFORM(loExcA1.ErrorNo) + ' [' + loExcA1.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-BULD-212'
|
||||
IF FOUND()
|
||||
REPLACE cant WITH 1, pret_val WITH 1000, pretd WITH 1000, pret WITH ROUND(1000*5,4), ;
|
||||
pret_lei WITH ROUND(1000*5,4), cota_tva WITH 21
|
||||
ENDIF
|
||||
|
||||
gcMockArtCodmat = 'ART-A8-371'
|
||||
TRY
|
||||
goObj.do_adauga_articol()
|
||||
CATCH TO loExcA2
|
||||
DO McLog WITH 'EROARE do_adauga_articol (2) ' + TRANSFORM(loExcA2.ErrorNo) + ' [' + loExcA2.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-A8-371'
|
||||
IF FOUND()
|
||||
REPLACE cant WITH 1, pret_val WITH 500, pretd WITH 500, pret WITH ROUND(500*5,4), ;
|
||||
pret_lei WITH ROUND(500*5,4), cota_tva WITH 11
|
||||
ENDIF
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
=Assert3('2-doua articole in rul_temp', RECCOUNT_ACTIVE('rul_temp'), 2)
|
||||
|
||||
DO HarnessStep WITH 1, 'articole (21% si 11%) adaugate'
|
||||
|
||||
*========================= sincronizeaza() (declanseaza sparge_document) =========================
|
||||
LOCAL llEroareSync
|
||||
llEroareSync = .F.
|
||||
TRY
|
||||
goObj.sincronizeaza()
|
||||
CATCH TO loExcS
|
||||
llEroareSync = .T.
|
||||
DO McLog WITH 'EROARE sincronizeaza() ' + TRANSFORM(loExcS.ErrorNo) + ' [' + loExcS.Message + '] in ' + loExcS.Procedure + ':' + TRANSFORM(loExcS.LineNo)
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
=Assert3('3-sincronizeaza() fara eroare', IIF(llEroareSync,0,1), 1)
|
||||
|
||||
*========================= G: discountul se sparge pe cote (baza TVA-ului) =========================
|
||||
LOCAL lnCntG, lnSumGVal, lnSumG
|
||||
STORE 0 TO lnCntG, lnSumGVal, lnSumG
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'G'
|
||||
lnCntG = lnCntG + 1
|
||||
lnSumGVal = lnSumGVal + suma_val
|
||||
lnSumG = lnSumG + suma
|
||||
ENDSCAN
|
||||
=Assert3('4-doua randuri G (unul pe cota)', lnCntG, 2)
|
||||
=Assert3('4a-total discount valuta pastrat', lnSumGVal, 150.00)
|
||||
=Assert3('4b-total discount lei pastrat', lnSumG, 750.00)
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'G' AND ptva == 21
|
||||
=Assert3('5-G(21%) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('5a-G(21%).suma_val=100.00 (150*1000/1500)', suma_val, 100.00)
|
||||
=Assert3('5b-G(21%).suma=500.00', suma, 500.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO McLog WITH ' FAIL 5a-5b: G(21%) negasit'
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'G' AND ptva == 11
|
||||
=Assert3('6-G(11%) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('6a-G(11%).suma_val=50.00 (150*500/1500)', suma_val, 50.00)
|
||||
=Assert3('6b-G(11%).suma=250.00', suma, 250.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO McLog WITH ' FAIL 6a-6b: G(11%) negasit'
|
||||
ENDIF
|
||||
|
||||
*========================= T-uri: TVA DVI in RON, protejat, spart pe cote =========================
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'T' AND ptva == 21
|
||||
=Assert3('7-T(21%) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('8-T(21%).suma=945.00 (1192.50*210/265)', suma, 945.00)
|
||||
=Assert3('8a-T(21%).suma_val=0 (TVA DVI in RON)', suma_val, 0)
|
||||
=Assert3('8b-T(21%) ramane rand DVI protejat', NVL(rand_dvi,0)+NVL(valuta_proprie,0), 2)
|
||||
=Assert3('9-T(21%) partener vamal', NVL(id_partc,0), 901)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO McLog WITH ' FAIL 8-9: T(21%) negasit'
|
||||
ENDIF
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'T' AND ptva == 11
|
||||
=Assert3('10-T(11%) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('11-T(11%).suma=247.50 (1192.50*55/265)', suma, 247.50)
|
||||
=Assert3('11a-T(11%).suma_val=0 (TVA DVI in RON)', suma_val, 0)
|
||||
=Assert3('12-T(11%) ramane rand DVI protejat', NVL(rand_dvi,0)+NVL(valuta_proprie,0), 2)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO McLog WITH ' FAIL 11-12: T(11%) negasit'
|
||||
ENDIF
|
||||
|
||||
LOCAL lnCntT, lnSumTVal, lnSumT
|
||||
STORE 0 TO lnCntT, lnSumTVal, lnSumT
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'T'
|
||||
lnCntT = lnCntT + 1
|
||||
lnSumTVal = lnSumTVal + suma_val
|
||||
lnSumT = lnSumT + suma
|
||||
ENDSCAN
|
||||
=Assert3('13-exact 2 randuri T (o cota fiecare)', lnCntT, 2)
|
||||
=Assert3('14-suma T-urilor (valuta) = 0 (DVI in RON)', lnSumTVal, 0)
|
||||
=Assert3('15-suma T-urilor (lei) = 1192.50 (totalul tastat pe DVI)', lnSumT, 1192.50)
|
||||
|
||||
*========================= S: cota randului de baza = cota articolelor lui =========================
|
||||
LOCAL lnCntS
|
||||
lnCntS = 0
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'S'
|
||||
lnCntS = lnCntS + 1
|
||||
ENDSCAN
|
||||
=Assert3('16-doua randuri S', lnCntS, 2)
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'S' AND ptva == 21
|
||||
=Assert3('17-S cu cota 21 (articolul de 1000)', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('17a-S(21%).suma_val=1000.00', suma_val, 1000.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO McLog WITH ' FAIL 17a: S(21%) negasit'
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'S' AND ptva == 11
|
||||
=Assert3('18-S cu cota 11 (articolul de 500)', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('18a-S(11%).suma_val=500.00', suma_val, 500.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO McLog WITH ' FAIL 18a: S(11%) negasit'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 2, 'T-uri DVI multicota verificate - suma val=' + TRANSFORM(lnSumTVal) + ' lei=' + TRANSFORM(lnSumT)
|
||||
|
||||
DO McLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO McLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO McLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 3, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO McLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE CreeazaRulTemp
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp ( ;
|
||||
id_rul N(20,0), an N(4,0), luna N(2,0), cod N(20,0);
|
||||
, serie C(100), nnir N(20,0), id_articol N(10,0), denumire C(100);
|
||||
, codmat C(50), codmatf C(50), codbare C(50), um C(20);
|
||||
, id_gestiune N(5,0), nume_gestiune C(50), cgest C(20), nr_pag N(2,0);
|
||||
, gestionar C(50), comisie_receptie1 C(50), comisie_receptie2 C(50), comisie_receptie3 C(50);
|
||||
, cant N(14,3), cante N(14,3), cont C(10), acont C(20);
|
||||
, pret N(18,4), tva N(18,4), valoare N(18,4), valtva N(18,4);
|
||||
, proc_tva N(5,2), pretv N(18,4), pretvtva N(18,4), tvav N(18,4);
|
||||
, valoarev N(18,4), valtvav N(18,4), proc_tvav N(5,2), adaos N(18,4);
|
||||
, adaos_tva N(18,4), valoare_adaos N(18,4), valtva_adaos N(18,4), procent N(10,3);
|
||||
, discunitar N(18,4), discount_tva N(18,4), valoare_discount N(18,4), valtva_discount N(18,4);
|
||||
, proc_disc N(7,3), pretd N(14,4), curs N(18,4), id_valuta N(10,0);
|
||||
, nume_val C(20), id_lucrare N(20,0), nrord C(100), id_responsabil N(10,0);
|
||||
, nresp C(100), resp_marca N(18,4), dataact T, id_util N(5,0);
|
||||
, util C(30), dataora T, id_sectie N(5,0), sectie C(50);
|
||||
, csectie C(10), alcooltutun N(1,0), datain T, dataout T;
|
||||
, id_fact N(20,0), id_gestiunec N(10,0), nume_gestiunec C(50), cgestc C(20);
|
||||
, id_responsabilc N(5,0), id_reteta N(10,0), reteta C(50), nrespc C(100);
|
||||
, respc_marca N(18,4), id_set N(20,0), id_tip_rulaj N(10,0), tip_rulaj C(50);
|
||||
, id_obiect_depozit N(10,0), id_rul_aux N(10,0), nract N(20,0), serie_act C(10);
|
||||
, dataoras T, id_utils N(10,0), lot C(30), adata_expirare T;
|
||||
, id_sucursala N(5,0), sucursala C(250), id_part_rez N(10,0), part_rez C(100);
|
||||
, id_lucrare_rez N(10,0), nrord_rez C(100), subgrupa C(100), grupa C(100);
|
||||
, id_subgrupa N(5,0), id_grupa N(5,0), in_stoc N(1,0), in_crm N(1,0);
|
||||
, id_furnizor N(10,0), furnizor C(100), id_jtva_coloana N(4,0), explicatie_tva C(100);
|
||||
, taxcode N(6,0), taxname C(254), saft_procent N(18,4), codnc8 C(20);
|
||||
, id_tara_origine N(4,0), cod_tara_origine C(5), tara_origine C(50), greutate N(12,4);
|
||||
, fdoc C(30), id_fdoc N(18,4);
|
||||
, pret_lei N(18,4), pret_val N(14,4), cota_tva N(6,2))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaIntrodc
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
FUNCTION RECCOUNT_ACTIVE
|
||||
LPARAMETERS tcAlias
|
||||
LOCAL lnSel, lnCnt
|
||||
lnSel = SELECT()
|
||||
SELECT (tcAlias)
|
||||
COUNT TO lnCnt FOR !DELETED()
|
||||
SELECT (lnSel)
|
||||
RETURN lnCnt
|
||||
ENDFUNC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO McLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO McLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE McErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO McLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE McLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES (IIF(TYPE('gcMockAcontCrt') = 'C', gcMockAcontCrt, ''))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VCONFIG_CONT_IREG' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (contpart C(10), fel_cont N(1), cu_inregistrari N(1), ;
|
||||
explic_cont C(100), exceptie C(10), pozitie N(1), invers N(1), gasit N(1))
|
||||
INSERT INTO (m.tcCursor) VALUES ('401', 0, 0, 'Furnizori', '', 0, 0, 0)
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 1, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 2, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (222, 'ACH. IMP. 11%', 1, 0, 'FO11B', 11, 223, 1, 3, 301205)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (223, 'TVA ACH. IMP. 11%', 1, 0, 'FO11T', 11, 1, 4, 301205)
|
||||
ENDPROC
|
||||
12
utile/Teste/achizitie_import/test_dvi_multicota.ps1
Normal file
12
utile/Teste/achizitie_import/test_dvi_multicota.ps1
Normal file
@@ -0,0 +1,12 @@
|
||||
# test_dvi_multicota.ps1 - wrapper peste harness-ul generic pentru TVA-ul pe DVI + discountul financiar
|
||||
# distribuite pe doua cote TVA (21%/11%).
|
||||
# powershell -ExecutionPolicy Bypass -File test_dvi_multicota.ps1
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Teste = $PSScriptRoot
|
||||
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
|
||||
-TestPrg (Join-Path $Teste 'test_dvi_multicota.prg') `
|
||||
-Steps @('factura_creata','articole_adaugate','sincronizare','final') `
|
||||
-ShotsDir (Join-Path $Teste 'screenshots_dvi_multicota') `
|
||||
-SyncDir (Join-Path $Teste 'uisync_dvi_multicota') `
|
||||
-StepTimeoutSec 180 `
|
||||
-ReadyTimeoutSec 180
|
||||
648
utile/Teste/achizitie_import/test_dvi_tva_manual.prg
Normal file
648
utile/Teste/achizitie_import/test_dvi_tva_manual.prg
Normal file
@@ -0,0 +1,648 @@
|
||||
* test_dvi_tva_manual.prg
|
||||
* Runda30 (F1, plan fizzy-imagining-parnas.md): TVA DVI editat MANUAL in dialog (valoare
|
||||
* diferita de baza*cota) trebuie sa supravietuiasca do_executa()/sincronizeaza() - motorul
|
||||
* trebuie sa marcheze randul T rezultat cu mod_manual=1 (semantica EXISTENTA, refolosita - vezi
|
||||
* garda deja prezenta in do_executa: "If Nvl(mod_manual,0) <> 1"), nu sa rescrie suma la
|
||||
* fiecare recalculare.
|
||||
* Verifica:
|
||||
* - DOC1 (TVA DVI manual, 1200.00 <> 1098.30 auto): randul T are mod_manual=1 si suma=1200.00,
|
||||
* verificat pe CURSORUL introdc (nu doar pe proprietatea din dialog), supravietuieste
|
||||
* do_executa() si sincronizeaza();
|
||||
* - DOC2 (control, TVA DVI = baza*cota, 1098.30 exact): randul T are mod_manual=0 (nu orice
|
||||
* rand DVI devine automat manual - doar cel cu valoare divergenta).
|
||||
*
|
||||
* ASUMPTIE (de confruntat cu implementarea reala): mod_manual se determina prin COMPARAREA
|
||||
* toDlg.dvi_tva_lei cu baza*cota (nu printr-un flag suplimentar de dirty in toDlg) - vezi
|
||||
* text plan sectiunea "F1 - modificari", do_adauga_factura.
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_dvi_tva_manual.ps1
|
||||
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_dvi_tva_manual_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_dvi_tva_manual\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO DcErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO DcLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO DcLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_cauta_nom_articole.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO DcLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
PUBLIC goMockValuta
|
||||
goMockValuta = CREATEOBJECT('Custom')
|
||||
goMockValuta.AddProperty('id_valuta', 978)
|
||||
goMockValuta.AddProperty('nume_val', 'EUR')
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnButon
|
||||
STORE 2 TO gnButon
|
||||
PUBLIC gcMockArtCodmat, gcMockAcontCrt
|
||||
gcMockArtCodmat = ''
|
||||
gcMockAcontCrt = ''
|
||||
PUBLIC gnMockRaspuns
|
||||
gnMockRaspuns = 6
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (moneda principala EUR, curs 5.23) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 5.23)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 601)
|
||||
poAct.AddProperty('partc', 'RAJA')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: perechi reale 21% -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 208, 'ACH. INT. 21%', 1, 0, 1, 'RO21B', 'RO21T', 21, 209)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 209, 'TVA ACH. INT. 21%', 1, 0, 1, 'RO21T', '', 21, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (3, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (4, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 208, 21, 'ACH. INT. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 209, 21, 'TVA ACH. INT. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
DO CreeazaRulTemp
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO DcLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F.)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO DcLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
*========================= DOC1: TVA DVI MANUAL (1200.00, diferit de auto 1098.30) =========================
|
||||
PUBLIC goDlg, goT
|
||||
DO AdaugaDoc WITH 15000, 'RAJA', 601, 1200.00
|
||||
DO HarnessStep WITH 0, 'dupa DOC1 (manual): introdc=' + TRANSFORM(RECCOUNT_ACTIVE('introdc')) + ' randuri'
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 15086 AND Nvl(rand_dvi,0) = 1
|
||||
=Assert3('1-DOC1: rand T-DVI gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
DO DcLog WITH 'DOC1 T-DVI: suma=' + TRANSFORM(suma) + ' mod_manual=' + TRANSFORM(NVL(mod_manual,0))
|
||||
=Assert3('2-DOC1: T-DVI.suma=1200.00 (valoare manuala, NU 1098.30 auto)', suma, 1200.00)
|
||||
=Assert3('3-DOC1: T-DVI.mod_manual=1 (dirty, valoare difera de baza*cota)', NVL(mod_manual,0), 1)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DcLog WITH ' FAIL 2-3: T-DVI DOC1 negasit'
|
||||
ENDIF
|
||||
|
||||
*-- garda do_executa (existenta - reutilizata prin mod_manual=1)
|
||||
goObj.do_executa()
|
||||
DOEVENTS FORCE
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 15086 AND Nvl(rand_dvi,0) = 1
|
||||
=Assert3('4-DOC1: dupa do_executa() suma ramane 1200.00', IIF(FOUND(),suma,-1), 1200.00)
|
||||
|
||||
*-- sincronizare completa
|
||||
LOCAL llEroareSync1
|
||||
llEroareSync1 = .F.
|
||||
TRY
|
||||
goObj.sincronizeaza()
|
||||
CATCH TO loExcS1
|
||||
llEroareSync1 = .T.
|
||||
DO DcLog WITH 'EROARE la sincronizeaza() DOC1 ' + TRANSFORM(loExcS1.ErrorNo) + ' [' + loExcS1.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
=Assert3('5-DOC1: sincronizeaza() fara eroare', IIF(llEroareSync1,0,1), 1)
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 15086 AND Nvl(rand_dvi,0) = 1
|
||||
=Assert3('6-DOC1: dupa sincronizeaza() suma ramane 1200.00', IIF(FOUND(),suma,-1), 1200.00)
|
||||
IF FOUND()
|
||||
=Assert3('7-DOC1: dupa sincronizeaza() mod_manual ramane 1', NVL(mod_manual,0), 1)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 1, 'DOC1 (TVA DVI manual) verificat - vezi log'
|
||||
|
||||
*========================= DOC2 (CONTROL): TVA DVI = baza*cota EXACT (1098.30) =========================
|
||||
DO AdaugaDoc WITH 15001, 'TRANS OIL', 602, 1098.30
|
||||
DO HarnessStep WITH 2, 'dupa DOC2 (control): introdc=' + TRANSFORM(RECCOUNT_ACTIVE('introdc')) + ' randuri'
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 15087 AND Nvl(rand_dvi,0) = 1
|
||||
=Assert3('8-DOC2: rand T-DVI gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
DO DcLog WITH 'DOC2 T-DVI: suma=' + TRANSFORM(suma) + ' mod_manual=' + TRANSFORM(NVL(mod_manual,0))
|
||||
=Assert3('9-DOC2: T-DVI.suma=1098.30 (auto, coincide cu baza*cota)', suma, 1098.30)
|
||||
=Assert3('10-DOC2: T-DVI.mod_manual=0 (nu e marcat manual - valoarea coincide cu auto-calc)', NVL(mod_manual,0), 0)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DcLog WITH ' FAIL 9-10: T-DVI DOC2 negasit'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 3, 'DOC2 (control, TVA auto) verificat - vezi log'
|
||||
|
||||
DO DcLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO DcLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO DcLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 4, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO DcLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE AdaugaDoc
|
||||
*-- FACTURA EUR curs 5.23, 1000 EUR (5230 lei), TVA pe DVI cu valuta facturii (fara
|
||||
*-- valuta_proprie - acest test tinteste STRICT supravietuirea valorii manuale, nu
|
||||
*-- independenta valutara, acoperita in celelalte 2 fisiere de test).
|
||||
LPARAMETERS tnNract, tcPartener, tnIdPartener, tnDviTvaLei
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = tnNract
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = tnIdPartener
|
||||
goDlg.cPartener = tcPartener
|
||||
goDlg.cExplicatia = 'Import marfa ' + tcPartener
|
||||
goDlg.nSuma = 1000
|
||||
goDlg.nSumaLei = 0
|
||||
goDlg.nCurs = 5.23
|
||||
goDlg.nIdValuta = 978
|
||||
goDlg.cValuta = 'EUR'
|
||||
goDlg.nIdExplicatieTva = 220
|
||||
goDlg.cExplicatieTva = 'ACH. IMP. 21%'
|
||||
goDlg.optTipTva.Value = 2 && D = DVI
|
||||
goDlg.chkInValutaCont.Value = 1
|
||||
goDlg.chkParticipaValuta.Value = 1
|
||||
goDlg.cSerieDvi = ''
|
||||
goDlg.nNractDvi = tnNract + 86
|
||||
goDlg.dDviData = DATE()
|
||||
goDlg.nIdFdocDVI = 2
|
||||
goDlg.cFelDocDvi = 'DVI'
|
||||
goDlg.nDviIdPartener = 900
|
||||
goDlg.cDviPartener = 'BIROUL VAMAL'
|
||||
goDlg.nDviTvaLei = tnDviTvaLei
|
||||
goDlg.nDviTvaVal = ROUND(tnDviTvaLei/5.23,4)
|
||||
*-- DVI cu valuta facturii (EUR) - fara valuta_proprie, ca sa izoleze testul pe mod_manual
|
||||
goDlg.nDviIdValuta = 978
|
||||
goDlg.cDviValuta = 'EUR'
|
||||
goDlg.nDviCurs = 5.23
|
||||
goDlg.actualizeaza_stare_dvi()
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO DcLog WITH 'DOC ' + TRANSFORM(tnNract) + ': valideaza = ' + TRANSFORM(goDlg.valideaza())
|
||||
DO ConstruiesteToDlgF1F2
|
||||
DO DcLog WITH 'DOC ' + TRANSFORM(tnNract) + ': do_adauga_factura = ' + TRANSFORM(goObj.do_adauga_factura(goT))
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE ConstruiesteToDlgF1F2
|
||||
goT = CREATEOBJECT('Empty')
|
||||
=ADDPROPERTY(goT,'serie_act',ALLTRIM(NVL(goDlg.cSerieAct,'')))
|
||||
=ADDPROPERTY(goT,'nract',goDlg.nNract)
|
||||
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
|
||||
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
|
||||
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
|
||||
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
|
||||
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
|
||||
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
|
||||
=ADDPROPERTY(goT,'suma',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,IIF(goDlg.nSumaLei<>0,goDlg.nSumaLei,ROUND(goDlg.nSuma*goDlg.nCurs,gnPC)),goDlg.nSuma))
|
||||
=ADDPROPERTY(goT,'suma_val',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,goDlg.nSuma,0))
|
||||
=ADDPROPERTY(goT,'in_valuta',goDlg.chkInValutaCont.Value)
|
||||
=ADDPROPERTY(goT,'participa_valuta',(goDlg.chkParticipaValuta.Value=1))
|
||||
=ADDPROPERTY(goT,'id_valuta',IIF(goDlg.chkInValutaCont.Value=1,goDlg.nIdValuta,0))
|
||||
=ADDPROPERTY(goT,'curs',IIF(goDlg.chkInValutaCont.Value=1,goDlg.nCurs,0))
|
||||
=ADDPROPERTY(goT,'nume_val',IIF(goDlg.chkInValutaCont.Value=1,ALLTRIM(NVL(goDlg.cValuta,'')),''))
|
||||
=ADDPROPERTY(goT,'cTipTva',IIF(goDlg.optTipTva.Value=1,'F',IIF(goDlg.optTipTva.Value=2,'D','N')))
|
||||
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
|
||||
=ADDPROPERTY(goT,'dvi_serie',CHRTRAN(ALLTRIM(NVL(goDlg.cSerieDvi,'')),CHR(34),''))
|
||||
=ADDPROPERTY(goT,'dvi_nract',goDlg.nNractDvi)
|
||||
=ADDPROPERTY(goT,'dvi_dataact',goDlg.dDviData)
|
||||
=ADDPROPERTY(goT,'dvi_id_fdoc',goDlg.nIdFdocDVI)
|
||||
=ADDPROPERTY(goT,'dvi_fdoc',goDlg.cFelDocDvi)
|
||||
=ADDPROPERTY(goT,'dvi_id_partc',goDlg.nDviIdPartener)
|
||||
=ADDPROPERTY(goT,'dvi_partc',goDlg.cDviPartener)
|
||||
=ADDPROPERTY(goT,'dvi_scc','401')
|
||||
=ADDPROPERTY(goT,'dvi_tva_lei',goDlg.nDviTvaLei)
|
||||
=ADDPROPERTY(goT,'dvi_tva_val',goDlg.nDviTvaVal)
|
||||
=ADDPROPERTY(goT,'dvi_in_valuta',!(EMPTY(goDlg.cDviValuta) OR UPPER(ALLTRIM(NVL(goDlg.cDviValuta,'')))=='RON'))
|
||||
=ADDPROPERTY(goT,'dvi_id_valuta',goDlg.nDviIdValuta)
|
||||
=ADDPROPERTY(goT,'dvi_curs',goDlg.nDviCurs)
|
||||
=ADDPROPERTY(goT,'dvi_nume_val',ALLTRIM(NVL(goDlg.cDviValuta,'')))
|
||||
=ADDPROPERTY(goT,'dvi_valuta_proprie',IIF(!(EMPTY(goDlg.cDviValuta) OR UPPER(ALLTRIM(NVL(goDlg.cDviValuta,'')))=='RON') OR !(EMPTY(goDlg.cValuta) OR UPPER(ALLTRIM(NVL(goDlg.cValuta,'')))=='RON'),IIF(goDlg.nDviIdValuta<>goDlg.nIdValuta OR goDlg.nDviCurs<>goDlg.nCurs,1,0),0))
|
||||
=ADDPROPERTY(goT,'disc_baza_lei',0)
|
||||
=ADDPROPERTY(goT,'disc_baza_val',0)
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaRulTemp
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp ( ;
|
||||
id_rul N(20,0), an N(4,0), luna N(2,0), cod N(20,0);
|
||||
, serie C(100), nnir N(20,0), id_articol N(10,0), denumire C(100);
|
||||
, codmat C(50), codmatf C(50), codbare C(50), um C(20);
|
||||
, id_gestiune N(5,0), nume_gestiune C(50), cgest C(20), nr_pag N(2,0);
|
||||
, gestionar C(50), comisie_receptie1 C(50), comisie_receptie2 C(50), comisie_receptie3 C(50);
|
||||
, cant N(14,3), cante N(14,3), cont C(10), acont C(20);
|
||||
, pret N(18,4), tva N(18,4), valoare N(18,4), valtva N(18,4);
|
||||
, proc_tva N(5,2), pretv N(18,4), pretvtva N(18,4), tvav N(18,4);
|
||||
, valoarev N(18,4), valtvav N(18,4), proc_tvav N(5,2), adaos N(18,4);
|
||||
, adaos_tva N(18,4), valoare_adaos N(18,4), valtva_adaos N(18,4), procent N(10,3);
|
||||
, discunitar N(18,4), discount_tva N(18,4), valoare_discount N(18,4), valtva_discount N(18,4);
|
||||
, proc_disc N(7,3), pretd N(14,4), curs N(18,4), id_valuta N(10,0);
|
||||
, nume_val C(20), id_lucrare N(20,0), nrord C(100), id_responsabil N(10,0);
|
||||
, nresp C(100), resp_marca N(18,4), dataact T, id_util N(5,0);
|
||||
, util C(30), dataora T, id_sectie N(5,0), sectie C(50);
|
||||
, csectie C(10), alcooltutun N(1,0), datain T, dataout T;
|
||||
, id_fact N(20,0), id_gestiunec N(10,0), nume_gestiunec C(50), cgestc C(20);
|
||||
, id_responsabilc N(5,0), id_reteta N(10,0), reteta C(50), nrespc C(100);
|
||||
, respc_marca N(18,4), id_set N(20,0), id_tip_rulaj N(10,0), tip_rulaj C(50);
|
||||
, id_obiect_depozit N(10,0), id_rul_aux N(10,0), nract N(20,0), serie_act C(10);
|
||||
, dataoras T, id_utils N(10,0), lot C(30), adata_expirare T;
|
||||
, id_sucursala N(5,0), sucursala C(250), id_part_rez N(10,0), part_rez C(100);
|
||||
, id_lucrare_rez N(10,0), nrord_rez C(100), subgrupa C(100), grupa C(100);
|
||||
, id_subgrupa N(5,0), id_grupa N(5,0), in_stoc N(1,0), in_crm N(1,0);
|
||||
, id_furnizor N(10,0), furnizor C(100), id_jtva_coloana N(4,0), explicatie_tva C(100);
|
||||
, taxcode N(6,0), taxname C(254), saft_procent N(18,4), codnc8 C(20);
|
||||
, id_tara_origine N(4,0), cod_tara_origine C(5), tara_origine C(50), greutate N(12,4);
|
||||
, fdoc C(30), id_fdoc N(18,4);
|
||||
, pret_lei N(18,4), pret_val N(14,4), cota_tva N(6,2))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaIntrodc
|
||||
*-- Runda30 (F1/pas2): coloane NOI rand_dvi N(1), valuta_proprie N(1) fata de structura veche.
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
FUNCTION RECCOUNT_ACTIVE
|
||||
LPARAMETERS tcAlias
|
||||
LOCAL lnSel, lnCnt
|
||||
lnSel = SELECT()
|
||||
SELECT (tcAlias)
|
||||
COUNT TO lnCnt FOR !DELETED()
|
||||
SELECT (lnSel)
|
||||
RETURN lnCnt
|
||||
ENDFUNC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO DcLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO DcLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE AssertStr
|
||||
LPARAMETERS tcLabel, tcActual, tcExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF tcActual == tcExpected
|
||||
pnPass = pnPass + 1
|
||||
DO DcLog WITH ' PASS ' + tcLabel + ' (=[' + tcActual + '])'
|
||||
ELSE
|
||||
DO DcLog WITH ' FAIL ' + tcLabel + ' (actual=[' + tcActual + '] asteptat=[' + tcExpected + '])'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DcErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO DcLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DcLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES (IIF(TYPE('gcMockAcontCrt') = 'C', gcMockAcontCrt, ''))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES ('371', '4')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (208, 'ACH. INT. 21%', 1, 0, 'RO21B', 21, 209, 1, 1, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (209, 'TVA ACH. INT. 21%', 1, 0, 'RO21T', 21, 1, 2, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 3, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 4, 301204)
|
||||
ENDPROC
|
||||
12
utile/Teste/achizitie_import/test_dvi_tva_manual.ps1
Normal file
12
utile/Teste/achizitie_import/test_dvi_tva_manual.ps1
Normal file
@@ -0,0 +1,12 @@
|
||||
# test_dvi_tva_manual.ps1 - wrapper peste harness-ul generic pentru TVA DVI editat manual in
|
||||
# dialog (supravietuieste do_executa/sincronizeaza) - F1, runda30.
|
||||
# powershell -ExecutionPolicy Bypass -File test_dvi_tva_manual.ps1
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Teste = $PSScriptRoot
|
||||
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
|
||||
-TestPrg (Join-Path $Teste 'test_dvi_tva_manual.prg') `
|
||||
-Steps @('doc1_manual_creat','doc1_manual_verificat','doc2_control_creat','doc2_control_verificat','final') `
|
||||
-ShotsDir (Join-Path $Teste 'screenshots_dvi_tva_manual') `
|
||||
-SyncDir (Join-Path $Teste 'uisync_dvi_tva_manual') `
|
||||
-StepTimeoutSec 180 `
|
||||
-ReadyTimeoutSec 180
|
||||
769
utile/Teste/achizitie_import/test_dvi_valuta_proprie_usd.prg
Normal file
769
utile/Teste/achizitie_import/test_dvi_valuta_proprie_usd.prg
Normal file
@@ -0,0 +1,769 @@
|
||||
* test_dvi_valuta_proprie_usd.prg
|
||||
* Runda30 (F1, plan fizzy-imagining-parnas.md): factura import EUR (curs 5.23) cu TVA DVI in
|
||||
* USD (curs 4.00) - a treia valuta, aleasa direct pe blocul DVI din dialog, NU printr-un al
|
||||
* doilea document DVI separat (spre deosebire de test_valuta_dvi_usd.prg, care acopera fluxul
|
||||
* VECHI cu doua documente - ramane neatins, regresie separata).
|
||||
* Verifica:
|
||||
* - randul T (TVA DVI) poarta valuta/curs proprii (USD/4.00), rand_dvi=1, valuta_proprie=1;
|
||||
* - spargere pe cote (sparge_document, prin sincronizeaza cu articole): T-ul protejat ramane
|
||||
* neatins si NU se naste niciun rand T suplimentar pe factura - TVA-ul documentului e
|
||||
* integral cel de pe DVI (altfel iese TVA dubla: o data pe DVI, o data pe factura);
|
||||
* - caz "singurul T e cel protejat" cu o singura cota pe articole: randul protejat ramane
|
||||
* neschimbat (spargerea pe cote se face doar cand articolele au cote diferite);
|
||||
* - editarea cursului pe randul T protejat in grila NU modifica Thisform.oact.curs si NU
|
||||
* corupe preturile articolelor (rul_temp);
|
||||
* - revert valuta_proprie: re-alegerea valutei documentului (EUR) pe randul protejat il
|
||||
* reseteaza la valuta_proprie=0.
|
||||
*
|
||||
* ASUMPTII (de confruntat cu implementarea reala):
|
||||
* - proprietatile de dialog nDviIdValuta/cDviValuta/nDviCurs, setate direct (fara picker);
|
||||
* - randul protejat se identifica prin rand_dvi=1 (index ord_doc nu distinge intre T-uri);
|
||||
* - revert-ul valuta_proprie se declanseaza prin Grid1.cValuta.Text1.DblClick (caut_valuta),
|
||||
* mock_caut_valuta.prg (contract vechi, valoare fixa) intoarce EUR - suficient pentru acest
|
||||
* test, deoarece valuta de revenit e chiar valuta facturii.
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_dvi_valuta_proprie_usd.ps1
|
||||
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_dvi_valuta_proprie_usd_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_dvi_valuta_proprie_usd\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO DcErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO DcLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO DcLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_cauta_nom_articole.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO DcLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
*----- goMockValuta: fix EUR (valuta facturii) - suficient pentru revert (Grid1.cValuta
|
||||
* DblClick alege valuta documentului). goMockValutaCoada pregatit pentru contractul nou. -----
|
||||
PUBLIC goMockValuta, goMockValutaCoada
|
||||
goMockValuta = CREATEOBJECT('Custom')
|
||||
goMockValuta.AddProperty('id_valuta', 978)
|
||||
goMockValuta.AddProperty('nume_val', 'EUR')
|
||||
goMockValutaCoada = CREATEOBJECT('Collection')
|
||||
LOCAL loValFact, loValDvi
|
||||
loValFact = CREATEOBJECT('Custom')
|
||||
loValFact.AddProperty('id_valuta', 978)
|
||||
loValFact.AddProperty('nume_val', 'EUR')
|
||||
goMockValutaCoada.Add(loValFact)
|
||||
loValDvi = CREATEOBJECT('Custom')
|
||||
loValDvi.AddProperty('id_valuta', 840)
|
||||
loValDvi.AddProperty('nume_val', 'USD')
|
||||
goMockValutaCoada.Add(loValDvi)
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnButon
|
||||
STORE 2 TO gnButon
|
||||
PUBLIC gcMockArtCodmat, gcMockAcontCrt
|
||||
gcMockArtCodmat = ''
|
||||
gcMockAcontCrt = ''
|
||||
PUBLIC gnMockRaspuns
|
||||
gnMockRaspuns = 6
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (moneda principala EUR, curs 5.23) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 5.23)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 601)
|
||||
poAct.AddProperty('partc', 'RAJA')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: perechi reale 21% -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 208, 'ACH. INT. 21%', 1, 0, 1, 'RO21B', 'RO21T', 21, 209)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 209, 'TVA ACH. INT. 21%', 1, 0, 1, 'RO21T', '', 21, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (3, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (4, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 208, 21, 'ACH. INT. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 209, 21, 'TVA ACH. INT. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
DO CreeazaRulTemp
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO DcLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F.)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO DcLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
*========================= DOC1: FACTURA EUR + TVA DVI in USD (valuta proprie) =========================
|
||||
PUBLIC goDlg, goT, gcDocKey1
|
||||
DO AdaugaDoc1
|
||||
DO HarnessStep WITH 0, 'dupa AdaugaDoc1: introdc=' + TRANSFORM(RECCOUNT_ACTIVE('introdc')) + ' randuri'
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('1-rand T-DVI gasit (rand_dvi=1)', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
gcDocKey1 = ALLTRIM(NVL(doc_key,''))
|
||||
DO DcLog WITH 'T-DVI: doc_key=[' + gcDocKey1 + '] suma=' + TRANSFORM(suma) + ' suma_val=' + TRANSFORM(suma_val) + ' curs=' + TRANSFORM(curs) + ' nume_val=[' + ALLTRIM(NVL(nume_val,'')) + ']'
|
||||
=Assert3('2-T-DVI.in_valuta=1 (USD e valuta)', NVL(in_valuta,0), 1)
|
||||
=Assert3('3-T-DVI.valuta_proprie=1 (USD <> EUR factura)', NVL(valuta_proprie,0), 1)
|
||||
=Assert3('4-T-DVI.id_valuta=840 (USD)', NVL(id_valuta,0), 840)
|
||||
=Assert3('5-T-DVI.curs=4.00', NVL(curs,0), 4.00)
|
||||
=AssertStr('6-T-DVI.nume_val=USD', ALLTRIM(NVL(nume_val,'?')), 'USD')
|
||||
=Assert3('7-T-DVI.suma_val=274.58 (1098.30/4.00)', suma_val, 274.58)
|
||||
ELSE
|
||||
DO DcLog WITH ' FAIL: nu exista rand T-DVI - sar restul verificarilor dependente'
|
||||
ENDIF
|
||||
|
||||
*========================= ARTICOLE (flux real do_adauga_articol) - documentul devine principal =========================
|
||||
gcMockArtCodmat = 'ART-A8-371'
|
||||
gcMockAcontCrt = '4'
|
||||
TRY
|
||||
goObj.do_adauga_articol()
|
||||
CATCH TO loExcA1
|
||||
DO DcLog WITH 'EROARE do_adauga_articol ' + TRANSFORM(loExcA1.ErrorNo) + ' [' + loExcA1.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-A8-371'
|
||||
IF FOUND()
|
||||
REPLACE cant WITH 1, pret_val WITH 1000, pretd WITH 1000, pret WITH ROUND(1000*5.23,4), pret_lei WITH ROUND(1000*5.23,4)
|
||||
ELSE
|
||||
DO DcLog WITH 'FAIL: articolul nu a fost adaugat de do_adauga_articol()'
|
||||
ENDIF
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
DO HarnessStep WITH 1, 'dupa adaugare articol, rul_temp=' + TRANSFORM(RECCOUNT_ACTIVE('rul_temp'))
|
||||
|
||||
*========================= SINCRONIZARE (declanseaza sparge_document: singurul T e cel protejat) =========================
|
||||
LOCAL llEroareSync
|
||||
llEroareSync = .F.
|
||||
TRY
|
||||
goObj.sincronizeaza()
|
||||
CATCH TO loExcS1
|
||||
llEroareSync = .T.
|
||||
DO DcLog WITH 'EROARE la sincronizeaza() ' + TRANSFORM(loExcS1.ErrorNo) + ' [' + loExcS1.Message + '] in ' + loExcS1.Procedure + ':' + TRANSFORM(loExcS1.LineNo)
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
=Assert3('8-sincronizeaza() fara eroare', IIF(llEroareSync,0,1), 1)
|
||||
DO DumpIntrodc
|
||||
|
||||
DO HarnessStep WITH 2, 'dupa sincronizare: introdc=' + TRANSFORM(RECCOUNT_ACTIVE('introdc')) + ' randuri'
|
||||
|
||||
*========================= T PROTEJAT SUPRAVIETUIESTE SPARGERII, NECOMASAT/NEATINS =========================
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('9-dupa sincronizare: T-DVI (rand_dvi=1) inca exista', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('10-T-DVI.suma_val neschimbata (274.58)', suma_val, 274.58)
|
||||
=Assert3('11-T-DVI.curs neschimbat (4.00)', curs, 4.00)
|
||||
=Assert3('12-T-DVI.valuta_proprie ramane 1', NVL(valuta_proprie,0), 1)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 3
|
||||
DO DcLog WITH ' FAIL 10-12: T-DVI a disparut dupa sincronizare (sparge_document l-a atins gresit)'
|
||||
ENDIF
|
||||
|
||||
*========================= NICIUN T SUPLIMENTAR PE FACTURA (TVA-ul e integral cel de pe DVI) =========================
|
||||
LOCAL lnCntTNormale, lnCntTTotal
|
||||
lnCntTNormale = 0
|
||||
lnCntTTotal = 0
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'T'
|
||||
lnCntTTotal = lnCntTTotal + 1
|
||||
IF Nvl(rand_dvi,0) = 0
|
||||
lnCntTNormale = lnCntTNormale + 1
|
||||
DO DcLog WITH 'T-duplicat: suma=' + TRANSFORM(suma) + ' suma_val=' + TRANSFORM(suma_val) + ' scd=[' + ALLTRIM(NVL(scd,'')) + '] partc=[' + ALLTRIM(NVL(partc,'')) + '] nume_val=[' + ALLTRIM(NVL(nume_val,'')) + ']'
|
||||
ENDIF
|
||||
ENDSCAN
|
||||
=Assert3('13-niciun rand T nou pe factura (TVA-ul e doar pe DVI)', lnCntTNormale, 0)
|
||||
=Assert3('14-un singur rand T pe document (articolele au o singura cota)', lnCntTTotal, 1)
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'T'
|
||||
IF FOUND()
|
||||
=Assert3('15-T-ul ramas e cel protejat (rand_dvi=1)', NVL(rand_dvi,0), 1)
|
||||
=AssertStr('16-T pastreaza valuta proprie USD', ALLTRIM(NVL(nume_val,'?')), 'USD')
|
||||
=Assert3('17-T pastreaza suma_val tastata (274.58)', suma_val, 274.58)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 3
|
||||
DO DcLog WITH ' FAIL 15-17: nu exista niciun rand T pe document'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 3, 'TVA doar pe randul DVI protejat (' + TRANSFORM(lnCntTTotal) + ' rand T pe document) - vezi log'
|
||||
|
||||
*========================= EDITARE CURS PE T PROTEJAT IN GRILA: oact.curs SI preturi articole NEATINSE =========================
|
||||
LOCAL lnCursInainte, lnPretInainte
|
||||
lnCursInainte = goObj.oact.curs
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-A8-371'
|
||||
lnPretInainte = IIF(FOUND(),pret,-1)
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('18-rand T-DVI gasit pentru editare curs in grila', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
goObj.grid1.cCurs.text1.Value = 4.50
|
||||
goObj.grid1.cCurs.text1.Valid()
|
||||
DOEVENTS FORCE
|
||||
ENDIF
|
||||
|
||||
=Assert3('19-dupa editare curs pe T-DVI: oact.curs NESCHIMBAT (5.23)', goObj.oact.curs, lnCursInainte)
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-A8-371'
|
||||
=Assert3('20-dupa editare curs pe T-DVI: pretul articolului NESCHIMBAT', IIF(FOUND(),pret,-1), lnPretInainte)
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
IF FOUND()
|
||||
=Assert3('21-T-DVI.curs actualizat local (4.50)', curs, 4.50)
|
||||
=Assert3('22-T-DVI.suma_val recalculata (1098.30/4.50=244.07)', suma_val, 244.07)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DcLog WITH ' FAIL 21-22: T-DVI negasit dupa editare curs in grila'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 4, 'editare curs pe T protejat verificata (oact.curs+preturi intacte) - vezi log'
|
||||
|
||||
*========================= REVERT valuta_proprie: re-alegerea valutei documentului (EUR) =========================
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('23-rand T-DVI gasit pentru revert valuta', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
TRY
|
||||
goObj.grid1.cValuta.text1.DblClick()
|
||||
CATCH TO loExcRevert
|
||||
DO DcLog WITH 'INFO cValuta.text1.DblClick a aruncat eroare (poate necesita alt trigger): ' + loExcRevert.Message
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
IF FOUND()
|
||||
DO DcLog WITH 'dupa revert: id_valuta=' + TRANSFORM(NVL(id_valuta,0)) + ' nume_val=[' + ALLTRIM(NVL(nume_val,'')) + '] valuta_proprie=' + TRANSFORM(NVL(valuta_proprie,0))
|
||||
=Assert3('24-dupa re-alegere valuta facturii (EUR) pe T-DVI: valuta_proprie reseteaza la 0', NVL(valuta_proprie,0), 0)
|
||||
=Assert3('25-dupa revert: id_valuta devine 978 (EUR, valuta facturii)', NVL(id_valuta,0), 978)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DcLog WITH ' FAIL 24-25: T-DVI negasit dupa incercarea de revert'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 5, 'revert valuta_proprie verificat - vezi log'
|
||||
|
||||
DO DcLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO DcLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO DcLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 6, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO DcLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE AdaugaDoc1
|
||||
*-- FACTURA 15000 RAJA, 1000 EUR curs 5.23 (5230 lei), TVA pe DVI ('D'): DVI 101 BIROUL
|
||||
*-- VAMAL, tva 1098.30 lei / 274.58 USD (curs propriu 4.00) - a treia valuta, diferita de
|
||||
*-- EUR (factura) si de RON.
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = 15000
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = 601
|
||||
goDlg.cPartener = 'RAJA'
|
||||
goDlg.cExplicatia = 'Import marfa RAJA'
|
||||
goDlg.nSuma = 1000
|
||||
goDlg.nSumaLei = 0
|
||||
goDlg.nCurs = 5.23
|
||||
goDlg.nIdValuta = 978
|
||||
goDlg.cValuta = 'EUR'
|
||||
goDlg.nIdExplicatieTva = 220
|
||||
goDlg.cExplicatieTva = 'ACH. IMP. 21%'
|
||||
goDlg.optTipTva.Value = 2 && D = DVI
|
||||
goDlg.chkInValutaCont.Value = 1
|
||||
goDlg.chkParticipaValuta.Value = 1
|
||||
goDlg.cSerieDvi = ''
|
||||
goDlg.nNractDvi = 101
|
||||
goDlg.dDviData = DATE()
|
||||
goDlg.nIdFdocDVI = 2
|
||||
goDlg.cFelDocDvi = 'DVI'
|
||||
goDlg.nDviIdPartener = 900
|
||||
goDlg.cDviPartener = 'BIROUL VAMAL'
|
||||
goDlg.nDviTvaLei = 1098.30
|
||||
goDlg.nDviTvaVal = 274.58
|
||||
*-- F1 NOU: valuta/curs proprii DVI - USD, a treia valuta (diferita de EUR/factura si de RON)
|
||||
goDlg.nDviIdValuta = 840
|
||||
goDlg.cDviValuta = 'USD'
|
||||
goDlg.nDviCurs = 4.00
|
||||
goDlg.actualizeaza_stare_dvi()
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO DcLog WITH 'DOC1: valideaza = ' + TRANSFORM(goDlg.valideaza())
|
||||
DO ConstruiesteToDlgF1F2
|
||||
DO DcLog WITH 'DOC1: do_adauga_factura = ' + TRANSFORM(goObj.do_adauga_factura(goT))
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE ConstruiesteToDlgF1F2
|
||||
goT = CREATEOBJECT('Empty')
|
||||
=ADDPROPERTY(goT,'serie_act',ALLTRIM(NVL(goDlg.cSerieAct,'')))
|
||||
=ADDPROPERTY(goT,'nract',goDlg.nNract)
|
||||
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
|
||||
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
|
||||
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
|
||||
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
|
||||
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
|
||||
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
|
||||
=ADDPROPERTY(goT,'suma',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,IIF(goDlg.nSumaLei<>0,goDlg.nSumaLei,ROUND(goDlg.nSuma*goDlg.nCurs,gnPC)),goDlg.nSuma))
|
||||
=ADDPROPERTY(goT,'suma_val',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,goDlg.nSuma,0))
|
||||
=ADDPROPERTY(goT,'in_valuta',goDlg.chkInValutaCont.Value)
|
||||
=ADDPROPERTY(goT,'participa_valuta',(goDlg.chkParticipaValuta.Value=1))
|
||||
=ADDPROPERTY(goT,'id_valuta',IIF(goDlg.chkInValutaCont.Value=1,goDlg.nIdValuta,0))
|
||||
=ADDPROPERTY(goT,'curs',IIF(goDlg.chkInValutaCont.Value=1,goDlg.nCurs,0))
|
||||
=ADDPROPERTY(goT,'nume_val',IIF(goDlg.chkInValutaCont.Value=1,ALLTRIM(NVL(goDlg.cValuta,'')),''))
|
||||
=ADDPROPERTY(goT,'cTipTva',IIF(goDlg.optTipTva.Value=1,'F',IIF(goDlg.optTipTva.Value=2,'D','N')))
|
||||
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
|
||||
=ADDPROPERTY(goT,'dvi_serie',CHRTRAN(ALLTRIM(NVL(goDlg.cSerieDvi,'')),CHR(34),''))
|
||||
=ADDPROPERTY(goT,'dvi_nract',goDlg.nNractDvi)
|
||||
=ADDPROPERTY(goT,'dvi_dataact',goDlg.dDviData)
|
||||
=ADDPROPERTY(goT,'dvi_id_fdoc',goDlg.nIdFdocDVI)
|
||||
=ADDPROPERTY(goT,'dvi_fdoc',goDlg.cFelDocDvi)
|
||||
=ADDPROPERTY(goT,'dvi_id_partc',goDlg.nDviIdPartener)
|
||||
=ADDPROPERTY(goT,'dvi_partc',goDlg.cDviPartener)
|
||||
=ADDPROPERTY(goT,'dvi_scc','401')
|
||||
=ADDPROPERTY(goT,'dvi_tva_lei',goDlg.nDviTvaLei)
|
||||
=ADDPROPERTY(goT,'dvi_tva_val',goDlg.nDviTvaVal)
|
||||
=ADDPROPERTY(goT,'dvi_in_valuta',!(EMPTY(goDlg.cDviValuta) OR UPPER(ALLTRIM(NVL(goDlg.cDviValuta,'')))=='RON'))
|
||||
=ADDPROPERTY(goT,'dvi_id_valuta',goDlg.nDviIdValuta)
|
||||
=ADDPROPERTY(goT,'dvi_curs',goDlg.nDviCurs)
|
||||
=ADDPROPERTY(goT,'dvi_nume_val',ALLTRIM(NVL(goDlg.cDviValuta,'')))
|
||||
=ADDPROPERTY(goT,'dvi_valuta_proprie',IIF(!(EMPTY(goDlg.cDviValuta) OR UPPER(ALLTRIM(NVL(goDlg.cDviValuta,'')))=='RON') OR !(EMPTY(goDlg.cValuta) OR UPPER(ALLTRIM(NVL(goDlg.cValuta,'')))=='RON'),IIF(goDlg.nDviIdValuta<>goDlg.nIdValuta OR goDlg.nDviCurs<>goDlg.nCurs,1,0),0))
|
||||
=ADDPROPERTY(goT,'disc_baza_lei',0)
|
||||
=ADDPROPERTY(goT,'disc_baza_val',0)
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaRulTemp
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp ( ;
|
||||
id_rul N(20,0), an N(4,0), luna N(2,0), cod N(20,0);
|
||||
, serie C(100), nnir N(20,0), id_articol N(10,0), denumire C(100);
|
||||
, codmat C(50), codmatf C(50), codbare C(50), um C(20);
|
||||
, id_gestiune N(5,0), nume_gestiune C(50), cgest C(20), nr_pag N(2,0);
|
||||
, gestionar C(50), comisie_receptie1 C(50), comisie_receptie2 C(50), comisie_receptie3 C(50);
|
||||
, cant N(14,3), cante N(14,3), cont C(10), acont C(20);
|
||||
, pret N(18,4), tva N(18,4), valoare N(18,4), valtva N(18,4);
|
||||
, proc_tva N(5,2), pretv N(18,4), pretvtva N(18,4), tvav N(18,4);
|
||||
, valoarev N(18,4), valtvav N(18,4), proc_tvav N(5,2), adaos N(18,4);
|
||||
, adaos_tva N(18,4), valoare_adaos N(18,4), valtva_adaos N(18,4), procent N(10,3);
|
||||
, discunitar N(18,4), discount_tva N(18,4), valoare_discount N(18,4), valtva_discount N(18,4);
|
||||
, proc_disc N(7,3), pretd N(14,4), curs N(18,4), id_valuta N(10,0);
|
||||
, nume_val C(20), id_lucrare N(20,0), nrord C(100), id_responsabil N(10,0);
|
||||
, nresp C(100), resp_marca N(18,4), dataact T, id_util N(5,0);
|
||||
, util C(30), dataora T, id_sectie N(5,0), sectie C(50);
|
||||
, csectie C(10), alcooltutun N(1,0), datain T, dataout T;
|
||||
, id_fact N(20,0), id_gestiunec N(10,0), nume_gestiunec C(50), cgestc C(20);
|
||||
, id_responsabilc N(5,0), id_reteta N(10,0), reteta C(50), nrespc C(100);
|
||||
, respc_marca N(18,4), id_set N(20,0), id_tip_rulaj N(10,0), tip_rulaj C(50);
|
||||
, id_obiect_depozit N(10,0), id_rul_aux N(10,0), nract N(20,0), serie_act C(10);
|
||||
, dataoras T, id_utils N(10,0), lot C(30), adata_expirare T;
|
||||
, id_sucursala N(5,0), sucursala C(250), id_part_rez N(10,0), part_rez C(100);
|
||||
, id_lucrare_rez N(10,0), nrord_rez C(100), subgrupa C(100), grupa C(100);
|
||||
, id_subgrupa N(5,0), id_grupa N(5,0), in_stoc N(1,0), in_crm N(1,0);
|
||||
, id_furnizor N(10,0), furnizor C(100), id_jtva_coloana N(4,0), explicatie_tva C(100);
|
||||
, taxcode N(6,0), taxname C(254), saft_procent N(18,4), codnc8 C(20);
|
||||
, id_tara_origine N(4,0), cod_tara_origine C(5), tara_origine C(50), greutate N(12,4);
|
||||
, fdoc C(30), id_fdoc N(18,4);
|
||||
, pret_lei N(18,4), pret_val N(14,4), cota_tva N(6,2))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaIntrodc
|
||||
*-- Runda30 (F1/pas2): coloane NOI rand_dvi N(1), valuta_proprie N(1) fata de structura veche.
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
FUNCTION RECCOUNT_ACTIVE
|
||||
LPARAMETERS tcAlias
|
||||
LOCAL lnSel, lnCnt
|
||||
lnSel = SELECT()
|
||||
SELECT (tcAlias)
|
||||
COUNT TO lnCnt FOR !DELETED()
|
||||
SELECT (lnSel)
|
||||
RETURN lnCnt
|
||||
ENDFUNC
|
||||
|
||||
PROCEDURE DumpIntrodc
|
||||
LOCAL lnSel
|
||||
lnSel = SELECT()
|
||||
SELECT introdc
|
||||
SCAN
|
||||
DO DcLog WITH ' recno=' + TRANSFORM(RECNO()) + ' nr_doc=' + TRANSFORM(NVL(nr_doc,0)) + ' nract=' + TRANSFORM(nract) + ' fdoc=[' + ALLTRIM(NVL(fdoc,'')) + '] tip_rand=' + tip_rand + ;
|
||||
' scd=' + ALLTRIM(scd) + ' scc=' + ALLTRIM(scc) + ' suma=' + TRANSFORM(suma) + ' suma_val=' + TRANSFORM(suma_val) + ;
|
||||
' rand_dvi=' + TRANSFORM(NVL(rand_dvi,0)) + ' valuta_proprie=' + TRANSFORM(NVL(valuta_proprie,0)) + ' doc_key=[' + ALLTRIM(doc_key) + ']'
|
||||
ENDSCAN
|
||||
SELECT (lnSel)
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO DcLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO DcLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE AssertStr
|
||||
LPARAMETERS tcLabel, tcActual, tcExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF tcActual == tcExpected
|
||||
pnPass = pnPass + 1
|
||||
DO DcLog WITH ' PASS ' + tcLabel + ' (=[' + tcActual + '])'
|
||||
ELSE
|
||||
DO DcLog WITH ' FAIL ' + tcLabel + ' (actual=[' + tcActual + '] asteptat=[' + tcExpected + '])'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DcErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO DcLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DcLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES (IIF(TYPE('gcMockAcontCrt') = 'C', gcMockAcontCrt, ''))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES ('371', '4')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (208, 'ACH. INT. 21%', 1, 0, 'RO21B', 21, 209, 1, 1, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (209, 'TVA ACH. INT. 21%', 1, 0, 'RO21T', 21, 1, 2, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 3, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 4, 301204)
|
||||
ENDPROC
|
||||
12
utile/Teste/achizitie_import/test_dvi_valuta_proprie_usd.ps1
Normal file
12
utile/Teste/achizitie_import/test_dvi_valuta_proprie_usd.ps1
Normal file
@@ -0,0 +1,12 @@
|
||||
# test_dvi_valuta_proprie_usd.ps1 - wrapper peste harness-ul generic pentru TVA DVI in a treia
|
||||
# valuta (USD), proprie fata de factura (EUR) - F1, runda30.
|
||||
# powershell -ExecutionPolicy Bypass -File test_dvi_valuta_proprie_usd.ps1
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Teste = $PSScriptRoot
|
||||
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
|
||||
-TestPrg (Join-Path $Teste 'test_dvi_valuta_proprie_usd.prg') `
|
||||
-Steps @('doc1_creat','articol_adaugat','sync_sparge','tva_doar_pe_dvi','curs_grid_protejat','revert_valuta_proprie','final') `
|
||||
-ShotsDir (Join-Path $Teste 'screenshots_dvi_valuta_proprie_usd') `
|
||||
-SyncDir (Join-Path $Teste 'uisync_dvi_valuta_proprie_usd') `
|
||||
-StepTimeoutSec 180 `
|
||||
-ReadyTimeoutSec 180
|
||||
948
utile/Teste/achizitie_import/test_dvi_valuta_ron.prg
Normal file
948
utile/Teste/achizitie_import/test_dvi_valuta_ron.prg
Normal file
@@ -0,0 +1,948 @@
|
||||
* test_dvi_valuta_ron.prg
|
||||
* Runda30 (F1, plan fizzy-imagining-parnas.md): factura import EUR (curs 5.23) cu TVA DVI
|
||||
* platita in RON (fara valuta proprie a DVI - selectie explicita, diferita de valuta facturii).
|
||||
* Verifica:
|
||||
* - randul T (TVA DVI) primeste rand_dvi=1, valuta_proprie=1 (RON <> EUR factura),
|
||||
* in_valuta=0, participa_valuta=.F.;
|
||||
* - suma T NU se schimba dupa do_executa()/sincronizeaza()/recalc_tva_document() explicit;
|
||||
* - suma T e imuna la schimbarea cursului facturii (copiaza_valoare sare randul protejat);
|
||||
* - footer TVA in valuta (recalculeaza/ntva_val) EXCLUDE randul T RON chiar daca suma_val
|
||||
* ar contine reziduu (assert direct pe filtrul participa_valuta din Sum);
|
||||
* - uneste_document (test izolat, cursor construit direct) nu comaseaza un rand T protejat;
|
||||
* - debifare in_valuta la nivel de document: randurile B/S se golesc de valuta, randul T
|
||||
* protejat ramane neschimbat (deja RON) si isi pastreaza valuta_proprie=1.
|
||||
*
|
||||
* ASUMPTII (de confruntat cu implementarea reala, vezi raportul catre orchestrator):
|
||||
* - proprietatile noi de dialog se numesc nDviIdValuta, cDviValuta, nDviCurs (RON = 0/''/0);
|
||||
* - toDlg.dvi_valuta_proprie e calculat de do_adauga_factura ca 1 cand valuta/curs DVI difera
|
||||
* de valuta/curs facturii (aici construit direct in ConstruiesteToDlgF1F2, ca proxy);
|
||||
* - recalc_tva_document primeste garda suplimentara Nvl(valuta_proprie,0)=0 langa mod_manual.
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_dvi_valuta_ron.ps1
|
||||
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_dvi_valuta_ron_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_dvi_valuta_ron\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO DcErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO DcLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO DcLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_cauta_nom_articole.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO DcLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
*----- goMockValuta (contract vechi, folosit ca fallback) + goMockValutaCoada (contract nou,
|
||||
* coada FIFO - pregatit aici pentru cand mock_caut_valuta.prg va fi actualizat separat;
|
||||
* acest test NU invoca picker-ul cmdValuta/cmdDviValuta.Click, seteaza id_valuta/curs
|
||||
* direct pe dialog, ca in testele existente). -----
|
||||
PUBLIC goMockValuta, goMockValutaCoada
|
||||
goMockValuta = CREATEOBJECT('Custom')
|
||||
goMockValuta.AddProperty('id_valuta', 978)
|
||||
goMockValuta.AddProperty('nume_val', 'EUR')
|
||||
goMockValutaCoada = CREATEOBJECT('Collection')
|
||||
LOCAL loValFact, loValDvi
|
||||
loValFact = CREATEOBJECT('Custom')
|
||||
loValFact.AddProperty('id_valuta', 978)
|
||||
loValFact.AddProperty('nume_val', 'EUR')
|
||||
goMockValutaCoada.Add(loValFact)
|
||||
loValDvi = CREATEOBJECT('Custom')
|
||||
loValDvi.AddProperty('id_valuta', 1)
|
||||
loValDvi.AddProperty('nume_val', 'RON')
|
||||
goMockValutaCoada.Add(loValDvi)
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnButon
|
||||
STORE 2 TO gnButon
|
||||
PUBLIC gcMockArtCodmat, gcMockAcontCrt
|
||||
gcMockArtCodmat = ''
|
||||
gcMockAcontCrt = ''
|
||||
PUBLIC gnMockRaspuns
|
||||
gnMockRaspuns = 6
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (moneda principala EUR, curs 5.23) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 5.23)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 601)
|
||||
poAct.AddProperty('partc', 'RAJA')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: perechi reale 21% -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 208, 'ACH. INT. 21%', 1, 0, 1, 'RO21B', 'RO21T', 21, 209)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 209, 'TVA ACH. INT. 21%', 1, 0, 1, 'RO21T', '', 21, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (3, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (4, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 208, 21, 'ACH. INT. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 209, 21, 'TVA ACH. INT. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
DO CreeazaRulTemp
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
*-- index ord_doc INAINTE de CREATEOBJECT (capcana p, docs/testare-ui-vfp.md)
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
DO DcLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F.)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO DcLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
*========================= DOC1: FACTURA EUR + TVA DVI in RON =========================
|
||||
PUBLIC goDlg, goT, gcDocKey1
|
||||
DO AdaugaDoc1
|
||||
DO HarnessStep WITH 0, 'dupa AdaugaDoc1: introdc=' + TRANSFORM(RECCOUNT_ACTIVE('introdc')) + ' randuri'
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('1-rand T-DVI gasit (rand_dvi=1)', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
gcDocKey1 = ALLTRIM(NVL(doc_key,''))
|
||||
DO DcLog WITH 'T-DVI: doc_key=[' + gcDocKey1 + '] suma=' + TRANSFORM(suma) + ' in_valuta=' + TRANSFORM(NVL(in_valuta,0)) + ' participa_valuta=' + TRANSFORM(participa_valuta) + ' valuta_proprie=' + TRANSFORM(NVL(valuta_proprie,0))
|
||||
=Assert3('2-T-DVI.in_valuta=0', NVL(in_valuta,0), 0)
|
||||
=Assert3('3-T-DVI.participa_valuta=.F.', IIF(participa_valuta,1,0), 0)
|
||||
=Assert3('4-T-DVI.valuta_proprie=1', NVL(valuta_proprie,0), 1)
|
||||
=Assert3('5-T-DVI.id_valuta=0', NVL(id_valuta,0), 0)
|
||||
=Assert3('6-T-DVI.curs=0', NVL(curs,0), 0)
|
||||
=AssertStr('7-T-DVI.nume_val=""', ALLTRIM(NVL(nume_val,'?')), '')
|
||||
=Assert3('8-T-DVI.suma=1098.30 (baza*cota auto, nemanual)', suma, 1098.30)
|
||||
=Assert3('9-T-DVI.mod_manual=0 (valoare auto)', NVL(mod_manual,0), 0)
|
||||
ELSE
|
||||
DO DcLog WITH ' FAIL: nu exista rand T-DVI - sar restul verificarilor dependente'
|
||||
ENDIF
|
||||
|
||||
*========================= GARDA do_executa (nu rescrie T protejat) =========================
|
||||
goObj.do_executa()
|
||||
DOEVENTS FORCE
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('10-dupa do_executa(): T-DVI.suma neschimbata (1098.30)', IIF(FOUND(),suma,-1), 1098.30)
|
||||
|
||||
*========================= GARDA recalc_tva_document (nu rescrie T protejat) =========================
|
||||
IF !EMPTY(gcDocKey1)
|
||||
TRY
|
||||
goObj.recalc_tva_document(gcDocKey1)
|
||||
CATCH TO loExcRtd
|
||||
DO DcLog WITH 'INFO recalc_tva_document a aruncat eroare (poate nu accepta parametru direct): ' + loExcRtd.Message
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('11-dupa recalc_tva_document(): T-DVI.suma neschimbata (1098.30)', IIF(FOUND(),suma,-1), 1098.30)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO DcLog WITH ' FAIL 11: gcDocKey1 gol, nu pot apela recalc_tva_document'
|
||||
ENDIF
|
||||
|
||||
*========================= SINCRONIZARE completa (pipeline complet) =========================
|
||||
LOCAL llEroareSync
|
||||
llEroareSync = .F.
|
||||
TRY
|
||||
goObj.sincronizeaza()
|
||||
CATCH TO loExcS1
|
||||
llEroareSync = .T.
|
||||
DO DcLog WITH 'EROARE la sincronizeaza() ' + TRANSFORM(loExcS1.ErrorNo) + ' [' + loExcS1.Message + '] in ' + loExcS1.Procedure + ':' + TRANSFORM(loExcS1.LineNo)
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
=Assert3('12-sincronizeaza() fara eroare', IIF(llEroareSync,0,1), 1)
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('13-dupa sincronizeaza(): rand T-DVI inca gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('14-dupa sincronizeaza(): T-DVI.suma neschimbata (1098.30)', suma, 1098.30)
|
||||
=Assert3('15-dupa sincronizeaza(): T-DVI.valuta_proprie ramane 1', NVL(valuta_proprie,0), 1)
|
||||
=Assert3('16-dupa sincronizeaza(): T-DVI.participa_valuta ramane .F.', IIF(participa_valuta,1,0), 0)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 3
|
||||
DO DcLog WITH ' FAIL 14-16: T-DVI a disparut dupa sincronizare'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 1, 'dupa garzi executie/recalc/sincronizare - vezi log'
|
||||
|
||||
*========================= FOOTER TVA VALUTA: participa_valuta exclude T-DVI din ntva_val =========================
|
||||
*-- injectez artificial un suma_val nenul pe T-DVI (bypass motor) - daca filtrul pe
|
||||
*-- participa_valuta e corect, ntva_val NU se schimba fata de o rulare fara injectie.
|
||||
LOCAL lnNtvaValInainte, lnNtvaValDupa
|
||||
goObj.recalculeaza()
|
||||
lnNtvaValInainte = goObj.ntva_val
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
IF FOUND()
|
||||
REPLACE suma_val WITH 999.99
|
||||
goObj.recalculeaza()
|
||||
lnNtvaValDupa = goObj.ntva_val
|
||||
DO DcLog WITH 'FOOTER: ntva_val inainte=' + TRANSFORM(lnNtvaValInainte) + ' dupa injectie suma_val=999.99 pe T-DVI: ' + TRANSFORM(lnNtvaValDupa)
|
||||
=Assert3('17-footer ntva_val NU include suma_val injectata pe T-DVI (participa_valuta=.F.)', ABS(lnNtvaValDupa - lnNtvaValInainte), 0)
|
||||
*-- recalculeaza() e agregare read-only dar scaneaza cu SUM/CALCULATE (scope ALL), care
|
||||
*-- muta pointerul de inregistrare la EOF - re-LOCATE inainte de REPLACE, altfel reset-ul
|
||||
*-- de mai jos rateaza randul T-DVI (ramane cu suma_val=999.99 injectat mai sus).
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
REPLACE suma_val WITH 0
|
||||
goObj.recalculeaza()
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO DcLog WITH ' FAIL 17: T-DVI negasit pentru testul de footer'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 2, 'footer TVA valuta verificat - vezi log'
|
||||
|
||||
*========================= IMUNITATE LA SCHIMBAREA CURSULUI FACTURII (copiaza_valoare) =========================
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'B'
|
||||
=Assert3('18-rand B gasit pentru schimbare curs', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
goObj.grid1.cCurs.text1.Value = 6.00
|
||||
goObj.grid1.cCurs.text1.Valid()
|
||||
DOEVENTS FORCE
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
IF FOUND()
|
||||
=Assert3('19-dupa schimbare curs factura: T-DVI.curs ramane 0', NVL(curs,0), 0)
|
||||
=Assert3('20-dupa schimbare curs factura: T-DVI.suma_val ramane 0', NVL(suma_val,0), 0)
|
||||
=Assert3('21-dupa schimbare curs factura: T-DVI.suma neschimbata (1098.30)', suma, 1098.30)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 3
|
||||
DO DcLog WITH ' FAIL 19-21: T-DVI negasit dupa schimbare curs factura'
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'B'
|
||||
IF FOUND()
|
||||
=Assert3('22-randul B a primit noul curs (6.00, propagare normala)', curs, 6.00)
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 3, 'imunitate curs verificata - vezi log'
|
||||
|
||||
*========================= DEBIFARE in_valuta LA NIVEL DE DOCUMENT, CU T PROTEJAT =========================
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND tip_rand == 'B'
|
||||
=Assert3('23-rand B gasit pentru debifare in_valuta', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
goObj.grid1.cInValuta.check1.Value = 0
|
||||
goObj.grid1.cInValuta.check1.Valid()
|
||||
=Assert3('24-armare lSyncPending dupa debifare (pre-DOEVENTS)', IIF(goObj.lSyncPending,1,0), 1)
|
||||
DOEVENTS FORCE
|
||||
=Assert3('25-sync consumat dupa debifare', IIF(goObj.lSyncPending,1,0), 0)
|
||||
ENDIF
|
||||
LOCAL lnCntBSGolite
|
||||
lnCntBSGolite = 0
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == gcDocKey1 AND INLIST(tip_rand,'B','S')
|
||||
lnCntBSGolite = lnCntBSGolite + 1
|
||||
=Assert3('26.'+TRANSFORM(RECNO())+'-B/S.in_valuta=0 dupa debifare', NVL(in_valuta,0), 0)
|
||||
=Assert3('27.'+TRANSFORM(RECNO())+'-B/S.curs=0 dupa debifare', NVL(curs,0), 0)
|
||||
ENDSCAN
|
||||
=Assert3('28-cel putin un rand B/S golit', IIF(lnCntBSGolite>0,1,0), 1)
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
IF FOUND()
|
||||
=Assert3('29-T-DVI ramane in_valuta=0 dupa debifare document (nu s-a schimbat)', NVL(in_valuta,0), 0)
|
||||
=Assert3('30-T-DVI ramane valuta_proprie=1 dupa debifare document (nu se reseteaza)', NVL(valuta_proprie,0), 1)
|
||||
=Assert3('31-T-DVI.suma neschimbata (1098.30) dupa debifare document', suma, 1098.30)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 3
|
||||
DO DcLog WITH ' FAIL 29-31: T-DVI negasit dupa debifare document'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 4, 'debifare in_valuta cu T protejat verificata - vezi log'
|
||||
|
||||
*========================= UNESTE_DOCUMENT CU RAND T PROTEJAT (cursor izolat, construit direct) =========================
|
||||
DO TestUnesteDocumentCuProtejat
|
||||
|
||||
*========================= IDENTITATE PROPRIE PE RANDUL DVI (cursor izolat, construit direct) =========================
|
||||
DO TestIdentitateDviProtejata
|
||||
|
||||
DO DcLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO DcLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO DcLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 5, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO DcLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE AdaugaDoc1
|
||||
*-- FACTURA 15000 RAJA, 1000 EUR curs 5.23 (5230 lei), TVA pe DVI ('D'): DVI 101 BIROUL
|
||||
*-- VAMAL, tva 1098.30 lei, dar platita in RON (fara valuta proprie DVI) - diferita de
|
||||
*-- valuta facturii (EUR) => valuta_proprie=1 pe randul T rezultat.
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = 15000
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = 601
|
||||
goDlg.cPartener = 'RAJA'
|
||||
goDlg.cExplicatia = 'Import marfa RAJA'
|
||||
goDlg.nSuma = 1000
|
||||
goDlg.nSumaLei = 0
|
||||
goDlg.nCurs = 5.23
|
||||
goDlg.nIdValuta = 978
|
||||
goDlg.cValuta = 'EUR'
|
||||
goDlg.nIdExplicatieTva = 220
|
||||
goDlg.cExplicatieTva = 'ACH. IMP. 21%'
|
||||
goDlg.optTipTva.Value = 2 && D = DVI
|
||||
goDlg.chkInValutaCont.Value = 1
|
||||
goDlg.chkParticipaValuta.Value = 1
|
||||
goDlg.cSerieDvi = ''
|
||||
goDlg.nNractDvi = 101
|
||||
goDlg.dDviData = DATE()
|
||||
goDlg.nIdFdocDVI = 2
|
||||
goDlg.cFelDocDvi = 'DVI'
|
||||
goDlg.nDviIdPartener = 900
|
||||
goDlg.cDviPartener = 'BIROUL VAMAL'
|
||||
goDlg.nDviTvaLei = 1098.30
|
||||
goDlg.nDviTvaVal = 0
|
||||
*-- F1 NOU: valuta/curs proprii DVI - RON (fara valuta), explicit diferite de factura (EUR)
|
||||
goDlg.nDviIdValuta = 0
|
||||
goDlg.cDviValuta = ''
|
||||
goDlg.nDviCurs = 0
|
||||
goDlg.actualizeaza_stare_dvi()
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO DcLog WITH 'DOC1: valideaza = ' + TRANSFORM(goDlg.valideaza())
|
||||
DO ConstruiesteToDlgF1F2
|
||||
DO DcLog WITH 'DOC1: do_adauga_factura = ' + TRANSFORM(goObj.do_adauga_factura(goT))
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE ConstruiesteToDlgF1F2
|
||||
*-- toDlg construit INLINE (capcana l) - camp de baza + extensiile F1 (dvi_*) si F2 (discount,
|
||||
*-- neutre in acest test). Deciderul valutar al DVI e dvi_in_valuta (nu dvi_tva_val).
|
||||
goT = CREATEOBJECT('Empty')
|
||||
=ADDPROPERTY(goT,'serie_act',ALLTRIM(NVL(goDlg.cSerieAct,'')))
|
||||
=ADDPROPERTY(goT,'nract',goDlg.nNract)
|
||||
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
|
||||
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
|
||||
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
|
||||
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
|
||||
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
|
||||
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
|
||||
=ADDPROPERTY(goT,'suma',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,IIF(goDlg.nSumaLei<>0,goDlg.nSumaLei,ROUND(goDlg.nSuma*goDlg.nCurs,gnPC)),goDlg.nSuma))
|
||||
=ADDPROPERTY(goT,'suma_val',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,goDlg.nSuma,0))
|
||||
=ADDPROPERTY(goT,'in_valuta',goDlg.chkInValutaCont.Value)
|
||||
=ADDPROPERTY(goT,'participa_valuta',(goDlg.chkParticipaValuta.Value=1))
|
||||
=ADDPROPERTY(goT,'id_valuta',IIF(goDlg.chkInValutaCont.Value=1,goDlg.nIdValuta,0))
|
||||
=ADDPROPERTY(goT,'curs',IIF(goDlg.chkInValutaCont.Value=1,goDlg.nCurs,0))
|
||||
=ADDPROPERTY(goT,'nume_val',IIF(goDlg.chkInValutaCont.Value=1,ALLTRIM(NVL(goDlg.cValuta,'')),''))
|
||||
=ADDPROPERTY(goT,'cTipTva',IIF(goDlg.optTipTva.Value=1,'F',IIF(goDlg.optTipTva.Value=2,'D','N')))
|
||||
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
|
||||
=ADDPROPERTY(goT,'dvi_serie',CHRTRAN(ALLTRIM(NVL(goDlg.cSerieDvi,'')),CHR(34),''))
|
||||
=ADDPROPERTY(goT,'dvi_nract',goDlg.nNractDvi)
|
||||
=ADDPROPERTY(goT,'dvi_dataact',goDlg.dDviData)
|
||||
=ADDPROPERTY(goT,'dvi_id_fdoc',goDlg.nIdFdocDVI)
|
||||
=ADDPROPERTY(goT,'dvi_fdoc',goDlg.cFelDocDvi)
|
||||
=ADDPROPERTY(goT,'dvi_id_partc',goDlg.nDviIdPartener)
|
||||
=ADDPROPERTY(goT,'dvi_partc',goDlg.cDviPartener)
|
||||
=ADDPROPERTY(goT,'dvi_scc','401')
|
||||
=ADDPROPERTY(goT,'dvi_tva_lei',goDlg.nDviTvaLei)
|
||||
=ADDPROPERTY(goT,'dvi_tva_val',goDlg.nDviTvaVal)
|
||||
*-- F1 NOU: valuta/curs proprii ale DVI (deciderul e dvi_in_valuta, nu dvi_tva_val)
|
||||
=ADDPROPERTY(goT,'dvi_in_valuta',!(EMPTY(goDlg.cDviValuta) OR UPPER(ALLTRIM(NVL(goDlg.cDviValuta,'')))=='RON'))
|
||||
=ADDPROPERTY(goT,'dvi_id_valuta',goDlg.nDviIdValuta)
|
||||
=ADDPROPERTY(goT,'dvi_curs',goDlg.nDviCurs)
|
||||
=ADDPROPERTY(goT,'dvi_nume_val',ALLTRIM(NVL(goDlg.cDviValuta,'')))
|
||||
=ADDPROPERTY(goT,'dvi_valuta_proprie',IIF(!(EMPTY(goDlg.cDviValuta) OR UPPER(ALLTRIM(NVL(goDlg.cDviValuta,'')))=='RON') OR !(EMPTY(goDlg.cValuta) OR UPPER(ALLTRIM(NVL(goDlg.cValuta,'')))=='RON'),IIF(goDlg.nDviIdValuta<>goDlg.nIdValuta OR goDlg.nDviCurs<>goDlg.nCurs,1,0),0))
|
||||
*-- Runda32 (neutru in acest test - fara discount)
|
||||
=ADDPROPERTY(goT,'disc_baza_lei',0)
|
||||
=ADDPROPERTY(goT,'disc_baza_val',0)
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE TestUnesteDocumentCuProtejat
|
||||
*-- test izolat: cursor introdc construit DIRECT (nu prin dialog) cu un document ce are
|
||||
*-- 2 randuri T "normale" (mod_manual=0, valuta_proprie=0, de comasat) + 1 rand T protejat
|
||||
*-- (rand_dvi=1, valuta_proprie=1, mod_manual=0, NU trebuie comasat). Verifica ca
|
||||
*-- uneste_document() lasa randul protejat intact si comaseaza doar restul.
|
||||
LOCAL lcDocKeyX, lnCntTDupa
|
||||
lcDocKeyX = 'X|900001|0|0'
|
||||
|
||||
SELECT introdc
|
||||
APPEND BLANK
|
||||
REPLACE tip_rand WITH 'S', scd WITH '371', scc WITH '401', suma WITH 1000, suma_val WITH 0, ;
|
||||
nr_doc WITH 900001, nract WITH 900001, fdoc WITH 'Factura', doc_key WITH lcDocKeyX, ;
|
||||
mod_manual WITH 0, rand_dvi WITH 0, valuta_proprie WITH 0
|
||||
|
||||
APPEND BLANK
|
||||
REPLACE tip_rand WITH 'T', scd WITH '4426', scc WITH '401', suma WITH 100, suma_val WITH 0, ;
|
||||
ptva WITH 21, nr_doc WITH 900001, nract WITH 900001, fdoc WITH 'Factura', doc_key WITH lcDocKeyX, ;
|
||||
mod_manual WITH 0, rand_dvi WITH 0, valuta_proprie WITH 0
|
||||
|
||||
APPEND BLANK
|
||||
REPLACE tip_rand WITH 'T', scd WITH '4426', scc WITH '4427', suma WITH 110, suma_val WITH 0, ;
|
||||
ptva WITH 21, nr_doc WITH 900001, nract WITH 900001, fdoc WITH 'Factura', doc_key WITH lcDocKeyX, ;
|
||||
mod_manual WITH 0, rand_dvi WITH 0, valuta_proprie WITH 0
|
||||
|
||||
APPEND BLANK
|
||||
REPLACE tip_rand WITH 'T', scd WITH '4426', scc WITH '401', suma WITH 1098.30, suma_val WITH 0, ;
|
||||
ptva WITH 21, nr_doc WITH 900001, nract WITH 101, fdoc WITH 'DVI', partc WITH 'BIROUL VAMAL', ;
|
||||
doc_key WITH lcDocKeyX, mod_manual WITH 0, rand_dvi WITH 1, valuta_proprie WITH 1
|
||||
|
||||
TRY
|
||||
goObj.uneste_document(PADR(lcDocKeyX, 80))
|
||||
CATCH TO loExcU
|
||||
DO DcLog WITH 'EROARE uneste_document ' + TRANSFORM(loExcU.ErrorNo) + ' [' + loExcU.Message + '] in ' + loExcU.Procedure + ':' + TRANSFORM(loExcU.LineNo)
|
||||
ENDTRY
|
||||
|
||||
lnCntTDupa = 0
|
||||
SELECT introdc
|
||||
SCAN FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyX AND tip_rand == 'T'
|
||||
lnCntTDupa = lnCntTDupa + 1
|
||||
DO DcLog WITH 'UNESTE: rand T ramas rand_dvi=' + TRANSFORM(NVL(rand_dvi,0)) + ' valuta_proprie=' + TRANSFORM(NVL(valuta_proprie,0)) + ' suma=' + TRANSFORM(suma)
|
||||
ENDSCAN
|
||||
=Assert3('32-uneste_document: raman EXACT 2 randuri T (1 comasat + 1 protejat)', lnCntTDupa, 2)
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyX AND tip_rand == 'T' AND Nvl(rand_dvi,0) = 1
|
||||
=Assert3('33-uneste_document: randul protejat (rand_dvi=1) supravietuieste', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('34-uneste_document: randul protejat.suma neschimbata (1098.30)', suma, 1098.30)
|
||||
=Assert3('35-uneste_document: randul protejat.valuta_proprie ramane 1', NVL(valuta_proprie,0), 1)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 2
|
||||
DO DcLog WITH ' FAIL 34-35: randul protejat negasit dupa uneste_document'
|
||||
ENDIF
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyX AND tip_rand == 'T' AND Nvl(rand_dvi,0) = 0
|
||||
=Assert3('36-uneste_document: randul comasat (nemanual, nevaluta_proprie) exista', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('37-uneste_document: randul comasat.suma = 100+110 = 210', suma, 210)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO DcLog WITH ' FAIL 37: randul comasat negasit dupa uneste_document'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE TestIdentitateDviProtejata
|
||||
*-- test izolat: randul DVI (rand_dvi=1) trebuie sa isi pastreze identitatea PROPRIE
|
||||
*-- (nract, serie_act, partc, fdoc, id_fdoc) cand copiaza_valoare() propaga aceste campuri
|
||||
*-- pe grupul doc_key; un rand NORMAL din acelasi grup trebuie sa PRIMEASCA valoarea noua
|
||||
*-- (assert dublu per camp - altfel testul ar trece si daca propagarea s-ar strica de tot).
|
||||
*-- Verifica si coerenta doc_key pe grup dupa fiecare propagare (toate 5 campuri sunt chei -
|
||||
*-- llCheie regenereaza doc_key pe tot grupul, inclusiv pe randul protejat).
|
||||
LOCAL lcDocKeyX, lnRecnoB, lcDocKeyCrt
|
||||
lcDocKeyX = 'IDPROT|5001|1|601'
|
||||
|
||||
SELECT introdc
|
||||
APPEND BLANK
|
||||
REPLACE tip_rand WITH 'B', scd WITH '371', scc WITH '401', suma WITH 1000, ;
|
||||
nr_doc WITH 950001, nract WITH 5001, serie_act WITH 'FACT', id_fdoc WITH 1, fdoc WITH 'Factura', ;
|
||||
id_partc WITH 601, partc WITH 'FURNIZOR ORIGINAL', doc_key WITH lcDocKeyX, ;
|
||||
mod_manual WITH 0, rand_dvi WITH 0, valuta_proprie WITH 0
|
||||
|
||||
APPEND BLANK
|
||||
REPLACE tip_rand WITH 'S', scd WITH '4426', scc WITH '401', suma WITH 190, ;
|
||||
nr_doc WITH 950001, nract WITH 5001, serie_act WITH 'FACT', id_fdoc WITH 1, fdoc WITH 'Factura', ;
|
||||
id_partc WITH 601, partc WITH 'FURNIZOR ORIGINAL', doc_key WITH lcDocKeyX, ;
|
||||
mod_manual WITH 0, rand_dvi WITH 0, valuta_proprie WITH 0
|
||||
|
||||
APPEND BLANK
|
||||
REPLACE tip_rand WITH 'T', scd WITH '4426', scc WITH '401', suma WITH 95, ;
|
||||
nr_doc WITH 950001, nract WITH 9001, serie_act WITH 'VAMA', id_fdoc WITH 2, fdoc WITH 'DVI', ;
|
||||
id_partc WITH 900, partc WITH 'DIRECTIA VAMALA', doc_key WITH lcDocKeyX, ;
|
||||
mod_manual WITH 0, rand_dvi WITH 1, valuta_proprie WITH 1
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyX AND tip_rand == 'B'
|
||||
=Assert3('38-IDP: randul B gasit pentru test identitate DVI', IIF(FOUND(),1,0), 1)
|
||||
IF !FOUND()
|
||||
pnAsserts = pnAsserts + 20
|
||||
DO DcLog WITH ' FAIL 39-59: randul B negasit, sar restul testului de identitate DVI'
|
||||
RETURN
|
||||
ENDIF
|
||||
lnRecnoB = RECNO()
|
||||
|
||||
*-- NOTA: introdc e cursor PARTAJAT intre scenariile fisierului - alte scenarii (AdaugaDoc1,
|
||||
*-- TestUnesteDocumentCuProtejat) au deja propriile randuri rand_dvi=1/tip_rand='S' cu alt
|
||||
*-- doc_key. Fiecare LOCATE de mai jos e SCOPAT pe lcDocKeyCrt (doc_key-ul CURENT al
|
||||
*-- grupului, recalculat dupa fiecare propagare) - dublu rol: (a) evita sa gaseasca randul
|
||||
*-- altui scenariu, (b) FOUND() dupa scopare e chiar dovada de coerenta - daca doc_key nu
|
||||
*-- s-ar fi propagat uniform pe grup, randul n-ar mai fi gasit sub noul doc_key.
|
||||
|
||||
*-- 1. nract: 5001 -> 5002
|
||||
GO lnRecnoB
|
||||
REPLACE nract WITH 5002
|
||||
goObj.copiaza_valoare('nract')
|
||||
SELECT introdc
|
||||
GO lnRecnoB
|
||||
lcDocKeyCrt = ALLTRIM(NVL(doc_key,''))
|
||||
=Assert3('39-IDP nract: B.nract=5002 (propriu, control)', nract, 5002)
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyCrt AND Nvl(rand_dvi,0) = 1
|
||||
=Assert3('40-IDP nract: DVI gasit sub doc_key curent (coerenta grup)', IIF(FOUND(),1,0), 1)
|
||||
=Assert3('41-IDP nract: DVI.nract ramane 9001 (protejat)', NVL(nract,0), 9001)
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyCrt AND tip_rand == 'S'
|
||||
=Assert3('42-IDP nract: S gasit sub doc_key curent (coerenta grup)', IIF(FOUND(),1,0), 1)
|
||||
=Assert3('43-IDP nract: S.nract=5002 (propagat pe randul normal)', NVL(nract,0), 5002)
|
||||
|
||||
*-- 2. serie_act: 'FACT' -> 'FACT2'
|
||||
GO lnRecnoB
|
||||
REPLACE serie_act WITH 'FACT2'
|
||||
goObj.copiaza_valoare('serie_act')
|
||||
GO lnRecnoB
|
||||
lcDocKeyCrt = ALLTRIM(NVL(doc_key,''))
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyCrt AND Nvl(rand_dvi,0) = 1
|
||||
=Assert3('44-IDP serie_act: DVI gasit sub doc_key curent (coerenta grup)', IIF(FOUND(),1,0), 1)
|
||||
=AssertStr('45-IDP serie_act: DVI.serie_act ramane VAMA (protejat)', ALLTRIM(NVL(serie_act,'')), 'VAMA')
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyCrt AND tip_rand == 'S'
|
||||
=Assert3('46-IDP serie_act: S gasit sub doc_key curent (coerenta grup)', IIF(FOUND(),1,0), 1)
|
||||
=AssertStr('47-IDP serie_act: S.serie_act=FACT2 (propagat)', ALLTRIM(NVL(serie_act,'')), 'FACT2')
|
||||
|
||||
*-- 3. partc: 'FURNIZOR ORIGINAL' -> 'FURNIZOR NOU'
|
||||
GO lnRecnoB
|
||||
REPLACE partc WITH 'FURNIZOR NOU'
|
||||
goObj.copiaza_valoare('partc')
|
||||
GO lnRecnoB
|
||||
lcDocKeyCrt = ALLTRIM(NVL(doc_key,''))
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyCrt AND Nvl(rand_dvi,0) = 1
|
||||
=Assert3('48-IDP partc: DVI gasit sub doc_key curent (coerenta grup)', IIF(FOUND(),1,0), 1)
|
||||
=AssertStr('49-IDP partc: DVI.partc ramane DIRECTIA VAMALA (protejat)', ALLTRIM(NVL(partc,'')), 'DIRECTIA VAMALA')
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyCrt AND tip_rand == 'S'
|
||||
=Assert3('50-IDP partc: S gasit sub doc_key curent (coerenta grup)', IIF(FOUND(),1,0), 1)
|
||||
=AssertStr('51-IDP partc: S.partc=FURNIZOR NOU (propagat)', ALLTRIM(NVL(partc,'')), 'FURNIZOR NOU')
|
||||
|
||||
*-- 4. fdoc: 'Factura' -> 'Factura Noua'
|
||||
GO lnRecnoB
|
||||
REPLACE fdoc WITH 'Factura Noua'
|
||||
goObj.copiaza_valoare('fdoc')
|
||||
GO lnRecnoB
|
||||
lcDocKeyCrt = ALLTRIM(NVL(doc_key,''))
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyCrt AND Nvl(rand_dvi,0) = 1
|
||||
=Assert3('52-IDP fdoc: DVI gasit sub doc_key curent (coerenta grup)', IIF(FOUND(),1,0), 1)
|
||||
=AssertStr('53-IDP fdoc: DVI.fdoc ramane DVI (protejat)', ALLTRIM(NVL(fdoc,'')), 'DVI')
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyCrt AND tip_rand == 'S'
|
||||
=Assert3('54-IDP fdoc: S gasit sub doc_key curent (coerenta grup)', IIF(FOUND(),1,0), 1)
|
||||
=AssertStr('55-IDP fdoc: S.fdoc=Factura Noua (propagat)', ALLTRIM(NVL(fdoc,'')), 'Factura Noua')
|
||||
|
||||
*-- 5. id_fdoc: 1 -> 3
|
||||
GO lnRecnoB
|
||||
REPLACE id_fdoc WITH 3
|
||||
goObj.copiaza_valoare('id_fdoc')
|
||||
GO lnRecnoB
|
||||
lcDocKeyCrt = ALLTRIM(NVL(doc_key,''))
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyCrt AND Nvl(rand_dvi,0) = 1
|
||||
=Assert3('56-IDP id_fdoc: DVI gasit sub doc_key curent (coerenta grup finala)', IIF(FOUND(),1,0), 1)
|
||||
=Assert3('57-IDP id_fdoc: DVI.id_fdoc ramane 2 (protejat)', NVL(id_fdoc,0), 2)
|
||||
LOCATE FOR ALLTRIM(NVL(doc_key,'')) == lcDocKeyCrt AND tip_rand == 'S'
|
||||
=Assert3('58-IDP id_fdoc: S gasit sub doc_key curent (coerenta grup finala)', IIF(FOUND(),1,0), 1)
|
||||
=Assert3('59-IDP id_fdoc: S.id_fdoc=3 (propagat)', NVL(id_fdoc,0), 3)
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaRulTemp
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp ( ;
|
||||
id_rul N(20,0), an N(4,0), luna N(2,0), cod N(20,0);
|
||||
, serie C(100), nnir N(20,0), id_articol N(10,0), denumire C(100);
|
||||
, codmat C(50), codmatf C(50), codbare C(50), um C(20);
|
||||
, id_gestiune N(5,0), nume_gestiune C(50), cgest C(20), nr_pag N(2,0);
|
||||
, gestionar C(50), comisie_receptie1 C(50), comisie_receptie2 C(50), comisie_receptie3 C(50);
|
||||
, cant N(14,3), cante N(14,3), cont C(10), acont C(20);
|
||||
, pret N(18,4), tva N(18,4), valoare N(18,4), valtva N(18,4);
|
||||
, proc_tva N(5,2), pretv N(18,4), pretvtva N(18,4), tvav N(18,4);
|
||||
, valoarev N(18,4), valtvav N(18,4), proc_tvav N(5,2), adaos N(18,4);
|
||||
, adaos_tva N(18,4), valoare_adaos N(18,4), valtva_adaos N(18,4), procent N(10,3);
|
||||
, discunitar N(18,4), discount_tva N(18,4), valoare_discount N(18,4), valtva_discount N(18,4);
|
||||
, proc_disc N(7,3), pretd N(14,4), curs N(18,4), id_valuta N(10,0);
|
||||
, nume_val C(20), id_lucrare N(20,0), nrord C(100), id_responsabil N(10,0);
|
||||
, nresp C(100), resp_marca N(18,4), dataact T, id_util N(5,0);
|
||||
, util C(30), dataora T, id_sectie N(5,0), sectie C(50);
|
||||
, csectie C(10), alcooltutun N(1,0), datain T, dataout T;
|
||||
, id_fact N(20,0), id_gestiunec N(10,0), nume_gestiunec C(50), cgestc C(20);
|
||||
, id_responsabilc N(5,0), id_reteta N(10,0), reteta C(50), nrespc C(100);
|
||||
, respc_marca N(18,4), id_set N(20,0), id_tip_rulaj N(10,0), tip_rulaj C(50);
|
||||
, id_obiect_depozit N(10,0), id_rul_aux N(10,0), nract N(20,0), serie_act C(10);
|
||||
, dataoras T, id_utils N(10,0), lot C(30), adata_expirare T;
|
||||
, id_sucursala N(5,0), sucursala C(250), id_part_rez N(10,0), part_rez C(100);
|
||||
, id_lucrare_rez N(10,0), nrord_rez C(100), subgrupa C(100), grupa C(100);
|
||||
, id_subgrupa N(5,0), id_grupa N(5,0), in_stoc N(1,0), in_crm N(1,0);
|
||||
, id_furnizor N(10,0), furnizor C(100), id_jtva_coloana N(4,0), explicatie_tva C(100);
|
||||
, taxcode N(6,0), taxname C(254), saft_procent N(18,4), codnc8 C(20);
|
||||
, id_tara_origine N(4,0), cod_tara_origine C(5), tara_origine C(50), greutate N(12,4);
|
||||
, fdoc C(30), id_fdoc N(18,4);
|
||||
, pret_lei N(18,4), pret_val N(14,4), cota_tva N(6,2))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaIntrodc
|
||||
*-- Runda30 (F1/pas2): coloane NOI rand_dvi N(1), valuta_proprie N(1) fata de structura veche.
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
FUNCTION RECCOUNT_ACTIVE
|
||||
LPARAMETERS tcAlias
|
||||
LOCAL lnSel, lnCnt
|
||||
lnSel = SELECT()
|
||||
SELECT (tcAlias)
|
||||
COUNT TO lnCnt FOR !DELETED()
|
||||
SELECT (lnSel)
|
||||
RETURN lnCnt
|
||||
ENDFUNC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO DcLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO DcLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE AssertStr
|
||||
LPARAMETERS tcLabel, tcActual, tcExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF tcActual == tcExpected
|
||||
pnPass = pnPass + 1
|
||||
DO DcLog WITH ' PASS ' + tcLabel + ' (=[' + tcActual + '])'
|
||||
ELSE
|
||||
DO DcLog WITH ' FAIL ' + tcLabel + ' (actual=[' + tcActual + '] asteptat=[' + tcExpected + '])'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DcErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO DcLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE DcLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES (IIF(TYPE('gcMockAcontCrt') = 'C', gcMockAcontCrt, ''))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES ('371', '4')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (208, 'ACH. INT. 21%', 1, 0, 'RO21B', 21, 209, 1, 1, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (209, 'TVA ACH. INT. 21%', 1, 0, 'RO21T', 21, 1, 2, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 3, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 4, 301204)
|
||||
ENDPROC
|
||||
11
utile/Teste/achizitie_import/test_dvi_valuta_ron.ps1
Normal file
11
utile/Teste/achizitie_import/test_dvi_valuta_ron.ps1
Normal file
@@ -0,0 +1,11 @@
|
||||
# test_dvi_valuta_ron.ps1 - wrapper peste harness-ul generic pentru TVA DVI in RON (F1, runda30).
|
||||
# powershell -ExecutionPolicy Bypass -File test_dvi_valuta_ron.ps1
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$Teste = $PSScriptRoot
|
||||
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
|
||||
-TestPrg (Join-Path $Teste 'test_dvi_valuta_ron.prg') `
|
||||
-Steps @('doc1_creat','garzi_executie','footer_valuta','imunitate_curs','debifare_document','final') `
|
||||
-ShotsDir (Join-Path $Teste 'screenshots_dvi_valuta_ron') `
|
||||
-SyncDir (Join-Path $Teste 'uisync_dvi_valuta_ron') `
|
||||
-StepTimeoutSec 180 `
|
||||
-ReadyTimeoutSec 180
|
||||
951
utile/Teste/achizitie_import/test_e2e_dvi_ron_discount.prg
Normal file
951
utile/Teste/achizitie_import/test_e2e_dvi_ron_discount.prg
Normal file
@@ -0,0 +1,951 @@
|
||||
* test_e2e_dvi_ron_discount.prg
|
||||
* Runda30 (F1+F2) + Runda32 (model B/G/T, un singur rand G): test e2e pe SCENARIUL EXACT cerut
|
||||
* de Marius - factura de import in valuta (EUR), TVA DVI platit in RON (valuta proprie DVI,
|
||||
* diferita de a facturii), discount financiar (doar baza, fara bifa), articole adaugate, apoi
|
||||
* finalizare. Flux REAL: dialogul `import_adauga_factura` (nu insert direct in cursoare) +
|
||||
* `do_adauga_articol()` real + `sincronizeaza()` real.
|
||||
*
|
||||
* IMPORTANT: toDlg (contractul pentru do_adauga_factura) se construieste INLINE, in programul
|
||||
* PRINCIPAL, NU prin apelul `goDlg.construieste_todlg()` - capcana documentata deja in antetul
|
||||
* `mock_caut_valuta.prg` ("CREATEOBJECT/ADDPROPERTY nu merg corect apelate dintr-o procedura in
|
||||
* acest runtime"): confirmat prin diagnostic (28.07.2026) ca aceasta metoda arunca eroare 11
|
||||
* ("argument invalid") pe PRIMUL Addproperty, universal, pe orice instanta (inclusiv virgina),
|
||||
* dar EXACT ACELASI cod, apelat din programul principal cu goDlg.* in loc de This.*, functioneaza
|
||||
* corect. NU incerca sa "repari" apeland metoda direct - vezi handoff_dvi_discount.md pentru
|
||||
* dovezile complete (izolare fata de tip de date, mediu, mostenire de clasa, lungime de linie).
|
||||
*
|
||||
* Assert-uri rand cu rand pe `introdc` (sursa de adevar inainte de scrierea finala):
|
||||
* - randul B (baza factura): scd=371, suma=5000.00 (1000 EUR x curs 5), suma_val=1000.00,
|
||||
* in_valuta=1, id_valuta=978 (EUR), partener facturii;
|
||||
* - randul T-DVI (rand_dvi=1): scd=4426/scc=401, suma=840.00 (baza NETA lei x 21% =
|
||||
* (5000-1000)*21%, discountul scade baza DVI-ului), suma_val=0, in_valuta=0, id_valuta=0/
|
||||
* curs=0/nume_val='' (normalizare RON->fara valuta pe randul scris, desi pe dialog RON are
|
||||
* id real 1 - vezi conventia din handoff), participa_valuta=.F., partenerul vamal (DIRECTIA
|
||||
* VAMALA), mod_manual=1 (valoarea NETA difera de auto-calculul brut baza*cota=1050.00 facut
|
||||
* de do_adauga_factura la creare, deci randul e protejat de do_executa - vezi Runda32);
|
||||
* - randul G (discount, un singur rand, model B/G/T): scd = scc-ul randului B (analitic
|
||||
* mostenit), scc=767, suma=+1000.00, suma_val=+200.00 (POZITIV), id_partd = partenerul
|
||||
* facturii (de pe creditul B), participa_valuta=.F., cu_tva=0, ptva=0;
|
||||
* - pretul articolului (rul_temp) neafectat de discount: pret_lei=4000.00 (800 EUR x 5);
|
||||
* - randul D (diferenta), daca apare, e informativ (best-effort - nu il forteaza scenariul);
|
||||
* - totalurile din subsol (D4): txtftvalei/txtftvaval raman pe baza integrala (5000.00/
|
||||
* 1000.00); Text2/Text3 (cu TVA) scad discountul (4840.00 = 5000+840-1000, respectiv
|
||||
* 800.00 = 1000+0-200) - verificate imediat dupa Termin, inainte de a adauga articole
|
||||
* (documentul nu e inca spart pe randuri S, B ramane intreg pentru un calcul curat).
|
||||
*
|
||||
* Acoperea si cerinta FINALA (Runda32): factura de import in valuta + discount + TVA pe DVI,
|
||||
* cu assert-uri pe cele trei randuri (B/G/T) si pe totalurile din subsolul notei.
|
||||
*
|
||||
* PASUL FINAL "Terminat" (scrierea in `actactan` prin `import_nota.inainte_de_do_termin()`)
|
||||
* SE RULEAZA (nu mai e sarit). Acel cod deschide `Do Form verificare` (formular MODAL real,
|
||||
* `COMUN\ferestre\verificare.scx`, WindowType=1) - fara mock ar ramane blocat la nesfarsit.
|
||||
* Testul foloseste un STUB `verificare.scx` dedicat, in `stub_verificare\` (langa acest test,
|
||||
* NU peste formularul real) - form gol, `WindowType=0`, `Init` seteaza `gnButon=1` si
|
||||
* `Return .F.` (impiedica instantierea => `Do Form` revine imediat, fara afisare). Stub-ul
|
||||
* castiga rezolutia `Do Form` pentru ca `stub_verificare` e primul folder din `SET PATH`
|
||||
* (inaintea lui `COMUN\FERESTRE`, unde e formularul real) - confirmat empiric: `SET PATH`
|
||||
* rezolva pe ORDINEA din lista, primul folder cu fisierul cerut castiga.
|
||||
* Assert-uri suplimentare rand cu rand pe `actactan` (structura reala, fara `tip_rand`/
|
||||
* `rand_dvi` - randurile se identifica dupa scd/scc/semnul sumei): B (scd=371), T-DVI
|
||||
* (scd=4426, suma POZITIVA), G (scc=767, un singur rand) + niciun rand fals de finalizare NIR.
|
||||
*
|
||||
* Rulare:
|
||||
* powershell -ExecutionPolicy Bypass -File test_e2e_dvi_ron_discount.ps1
|
||||
|
||||
SET SAFETY OFF
|
||||
SET TALK OFF
|
||||
SET DELETED ON
|
||||
SET EXACT ON
|
||||
SET CENTURY ON
|
||||
SET DATE DMY
|
||||
SET DECIMALS TO 4
|
||||
SET NULLDISPLAY TO ''
|
||||
CLOSE DATABASES
|
||||
|
||||
PUBLIC gcUILog, gcSyncDir
|
||||
gcUILog = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\test_e2e_dvi_ron_discount_log.txt"
|
||||
gcSyncDir = "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\uisync_e2e_dvi_ron_discount\"
|
||||
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
|
||||
|
||||
ON ERROR DO EeErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
||||
ON SHUTDOWN QUIT
|
||||
|
||||
TRY
|
||||
LOCAL gcAppPath, lcPath
|
||||
gcAppPath = "D:\ROA\ROAGEST\"
|
||||
SET DEFAULT TO (gcAppPath)
|
||||
|
||||
lcPath = gcAppPath + 'COMUN\Utile\Teste\achizitie_import\stub_verificare;' + ;
|
||||
gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
|
||||
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
|
||||
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
|
||||
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
|
||||
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + gcAppPath + 'COMUN\MENIURI;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\GRIDEXTRAS;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
|
||||
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EXCEL;' + ;
|
||||
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
|
||||
SET PATH TO &lcPath ADDITIVE
|
||||
DO EeLog WITH 'SET PATH OK'
|
||||
|
||||
*----- CLASE -----
|
||||
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
|
||||
SET CLASSLIB TO GESTIUNI ADDITIVE
|
||||
SET CLASSLIB TO CAUT ADDITIVE
|
||||
SET CLASSLIB TO BAZA ADDITIVE
|
||||
SET CLASSLIB TO comun ADDITIVE
|
||||
SET CLASSLIB TO accessibility.vcx ADDITIVE
|
||||
SET CLASSLIB TO messagebox ADDITIVE
|
||||
SET CLASSLIB TO registry ADDITIVE
|
||||
SET CLASSLIB TO cauta_alfa_forms.vcx ADDITIVE
|
||||
SET CLASSLIB TO DECABAZA ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare ADDITIVE
|
||||
SET CLASSLIB TO stocuri.vcx ADDITIVE
|
||||
SET CLASSLIB TO rulaje.vcx ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_web ADDITIVE
|
||||
SET CLASSLIB TO ointroduceri_depozit ADDITIVE
|
||||
SET CLASSLIB TO overificari ADDITIVE
|
||||
SET CLASSLIB TO ferestre_oracle ADDITIVE
|
||||
SET CLASSLIB TO ferestre_cere_date.vcx ADDITIVE
|
||||
SET CLASSLIB TO configurare.vcx ADDITIVE
|
||||
SET CLASSLIB TO serii_numere.vcx ADDITIVE
|
||||
SET CLASSLIB TO omodificari.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocompensari.vcx ADDITIVE
|
||||
SET CLASSLIB TO caut_ora ADDITIVE
|
||||
SET CLASSLIB TO onote_contabile ADDITIVE
|
||||
SET CLASSLIB TO otoolbar ADDITIVE
|
||||
SET CLASSLIB TO bon_fisc ADDITIVE
|
||||
SET CLASSLIB TO onom_articole ADDITIVE
|
||||
SET CLASSLIB TO onom_retete ADDITIVE
|
||||
SET CLASSLIB TO orapoarte ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_gestiuni ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_parametri ADDITIVE
|
||||
SET CLASSLIB TO ONOM_CURS ADDITIVE
|
||||
SET CLASSLIB TO ctl32_statusbar_fals.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 ctl32_balloontip.vcx ADDITIVE
|
||||
SET CLASSLIB TO ocriterii.vcx ADDITIVE
|
||||
SET CLASSLIB TO oavize.vcx ADDITIVE
|
||||
SET CLASSLIB TO onomenclatoare2 ADDITIVE
|
||||
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
|
||||
SET CLASSLIB TO oimportxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO excelxml.vcx ADDITIVE
|
||||
SET CLASSLIB TO orapoarte_obinv.vcx ADDITIVE
|
||||
DO EeLog WITH 'SET CLASSLIB OK'
|
||||
|
||||
*----- PROCEDURI (mock-uri PRIMELE, ui_harness la final) -----
|
||||
SET PROCEDURE TO PROCEDURI
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_caut_valuta.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\mock_cauta_nom_articole.prg" ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\achizitie_import\mock_oscrie_in_fisiere.prg" ADDITIVE
|
||||
SET PROCEDURE TO acces_meniu ADDITIVE
|
||||
SET PROCEDURE TO cauta_alfa ADDITIVE
|
||||
SET PROCEDURE TO pmenu ADDITIVE
|
||||
SET PROCEDURE TO proceduri_comune ADDITIVE
|
||||
SET PROCEDURE TO quitapp ADDITIVE
|
||||
SET PROCEDURE TO init_program ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_listari.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_configurare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_articole.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_retete.prg ADDITIVE
|
||||
SET PROCEDURE TO orapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO mesaje ADDITIVE
|
||||
SET PROCEDURE TO oserii_numere.prg ADDITIVE
|
||||
SET PROCEDURE TO oexport.prg ADDITIVE
|
||||
SET PROCEDURE TO wwConfig.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_CURS.PRG ADDITIVE
|
||||
SET PROCEDURE TO validare.prg ADDITIVE
|
||||
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
|
||||
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
|
||||
SET PROCEDURE TO updateserver.prg ADDITIVE
|
||||
SET PROCEDURE TO oinainte_de.prg ADDITIVE
|
||||
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
|
||||
SET PROCEDURE TO Ocompensari.PRG ADDITIVE
|
||||
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_rulaje ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_stocuri ADDITIVE
|
||||
SET PROCEDURE TO OINTRODUCERI ADDITIVE
|
||||
SET PROCEDURE TO oHeader.prg ADDITIVE
|
||||
SET PROCEDURE TO proceduri_excel.PRG ADDITIVE
|
||||
SET PROCEDURE TO onomenclatoare.PRG ADDITIVE
|
||||
SET PROCEDURE TO osecurity ADDITIVE
|
||||
SET PROCEDURE TO ocautare ADDITIVE
|
||||
SET PROCEDURE TO orefaceri ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_comun.PRG ADDITIVE
|
||||
SET PROCEDURE TO ofacturare_stoc.PRG ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casademarcat ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_e500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_casa_marcat_mp500 ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
|
||||
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO ini.prg ADDITIVE
|
||||
SET PROCEDURE TO odocumente.prg ADDITIVE
|
||||
SET PROCEDURE TO regex.prg ADDITIVE
|
||||
SET PROCEDURE TO wwutils.prg ADDITIVE
|
||||
SET PROCEDURE TO inchidere_k ADDITIVE
|
||||
SET PROCEDURE TO iniacces.prg ADDITIVE
|
||||
SET PROCEDURE TO oupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO procese.prg ADDITIVE
|
||||
SET PROCEDURE TO version.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlaccess.prg ADDITIVE
|
||||
SET PROCEDURE TO xmlparser.prg ADDITIVE
|
||||
SET PROCEDURE TO filebringer.prg ADDITIVE
|
||||
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
|
||||
SET PROCEDURE TO wwhttp.prg ADDITIVE
|
||||
SET PROCEDURE TO xdate.prg ADDITIVE
|
||||
SET PROCEDURE TO ofacturare.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_obinv.prg ADDITIVE
|
||||
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
|
||||
SET PROCEDURE TO email.prg ADDITIVE
|
||||
SET PROCEDURE TO "D:\ROA\ROAGEST\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
|
||||
DO EeLog WITH 'SET PROCEDURE OK'
|
||||
|
||||
*----- Globale -----
|
||||
PUBLIC gnPc, gnPval, gnPcant, gnPpret, gnPPretval, gnPCurs, gnPVal, gnPPretV, gnPPretVal
|
||||
STORE 2 TO gnPc, gnPval, gnPVal
|
||||
gnPcant = 3
|
||||
STORE 4 TO gnPpret, gnPPretval, gnPPretVal, gnPPretV, gnPCurs
|
||||
PUBLIC gl406, gcS, gnAn, gnLuna, gnIdFirma, gnIdSucursala, gcAcces, gcFirma
|
||||
gl406 = .T.
|
||||
gcS = 'CONTAFIN'
|
||||
gnAn = YEAR(DATE())
|
||||
gnLuna = MONTH(DATE())
|
||||
gnIdFirma = 110
|
||||
gnIdSucursala = 110
|
||||
gcAcces = "1;2;3;4;5;6;7;8;"
|
||||
gcFirma = gcS
|
||||
PUBLIC nror(65000)
|
||||
|
||||
PUBLIC gnMockRaspuns, gcMockUltimMesaj, gnMockUltimTip, gcMockArtCodmat
|
||||
gnMockRaspuns = 6
|
||||
gcMockUltimMesaj = ''
|
||||
gnMockUltimTip = 0
|
||||
PUBLIC gnButon
|
||||
gnButon = 1
|
||||
gcMockArtCodmat = ''
|
||||
|
||||
PUBLIC goExecutor, goApp
|
||||
goExecutor = CREATEOBJECT('dummyexecutor')
|
||||
goApp = CREATEOBJECT('dummyapp')
|
||||
|
||||
*----- poAct: antetul notei (factura import EUR, curs 5) -----
|
||||
PUBLIC poAct
|
||||
poAct = CREATEOBJECT('Custom')
|
||||
poAct.AddProperty('nume_val', 'EUR')
|
||||
poAct.AddProperty('curs', 5)
|
||||
poAct.AddProperty('proc_tva', 1.21)
|
||||
poAct.AddProperty('nnir', 0)
|
||||
poAct.AddProperty('id_valuta', 978)
|
||||
poAct.AddProperty('id_fdoc', 1)
|
||||
poAct.AddProperty('fdoc', 'Factura')
|
||||
poAct.AddProperty('id_partc', 601)
|
||||
poAct.AddProperty('partc', 'FURNIZOR EXTERN GMBH')
|
||||
poAct.AddProperty('serie_act', '')
|
||||
poAct.AddProperty('dataact', DATE())
|
||||
poAct.AddProperty('tva_incasare', 0)
|
||||
poAct.AddProperty('id_set', 1)
|
||||
poAct.AddProperty('id_gestin', 1)
|
||||
|
||||
*----- jtva_coloane2 / saft_taxtable: perechi reale 21% (achizitii interne + import) -----
|
||||
IF USED('jtva_coloane2')
|
||||
USE IN ('jtva_coloane2')
|
||||
ENDIF
|
||||
CREATE CURSOR jtva_coloane2 (ordine N(8), id_jtva_coloana N(14), denumire C(100), ;
|
||||
jc N(1), jv N(1), afisat N(1), coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14))
|
||||
INSERT INTO jtva_coloane2 VALUES (0, 0, '', 0, 0, 1, '', '', 0, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (1, 208, 'ACH. INT. 21%', 1, 0, 1, 'RO21B', 'RO21T', 21, 209)
|
||||
INSERT INTO jtva_coloane2 VALUES (2, 209, 'TVA ACH. INT. 21%', 1, 0, 1, 'RO21T', '', 21, 0)
|
||||
INSERT INTO jtva_coloane2 VALUES (3, 220, 'ACH. IMP. 21%', 1, 0, 1, 'FO21B', 'FO21T', 21, 221)
|
||||
INSERT INTO jtva_coloane2 VALUES (4, 221, 'TVA ACH. IMP. 21%', 1, 0, 1, 'FO21T', '', 21, 0)
|
||||
|
||||
IF USED('saft_taxtable')
|
||||
USE IN ('saft_taxtable')
|
||||
ENDIF
|
||||
CREATE CURSOR saft_taxtable (taxname C(250) NULL, typename C(250) NULL, taxcode N(6) NULL, ;
|
||||
taxtype N(3) NULL, descriere C(250) NULL, tip C(100) NULL, descriere_tip C(250) NULL, ;
|
||||
procent_taxa N(7,2) NULL, procent_prorata N(7,2) NULL, inactiv N(1) NULL, tva N(1) NULL, ;
|
||||
wht N(1) NULL, tva_achizitii N(1) NULL, tva_livrari N(1) NULL)
|
||||
INDEX ON taxcode TAG taxcode
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('', 0, '', 0, 1, 1, 1, 1)
|
||||
INSERT INTO saft_taxtable (taxname, taxcode, descriere, procent_taxa, tva, wht, tva_achizitii, tva_livrari) ;
|
||||
VALUES ('301204-Import de bunuri cota 21%', 301204, '', 21, 1, 0, 1, 0)
|
||||
|
||||
DO CreeazaIntrodc WITH 'introdc'
|
||||
DO CreeazaIntrodc WITH 'introdc_sablon'
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('371', '401', 1, 1, 1, .T., 'B', 208, 21, 'ACH. INT. 21%')
|
||||
INSERT INTO introdc_sablon (scd, scc, cu_tva, ordine, id_set, participa_valuta, tip_rand, ;
|
||||
id_jtva_coloana, ptva, explicatie_tva) ;
|
||||
VALUES ('4426', '401', 1, 2, 1, .T., 'T', 209, 21, 'TVA ACH. INT. 21%')
|
||||
GO TOP IN introdc_sablon
|
||||
|
||||
DO CreeazaRulTemp
|
||||
INSERT INTO rul_temp (denumire, codmat, cant, pret, pret_lei, cont, cota_tva) ;
|
||||
VALUES ('PLACEHOLDER', 'PH', 1, 1, 1, '371', 21)
|
||||
|
||||
*-- index ord_doc INAINTE de CREATEOBJECT (capcana p, docs/testare-ui-vfp.md)
|
||||
SELECT introdc
|
||||
INDEX ON Str(Nvl(nr_doc,0),8) + Icase(tip_rand='B','1', tip_rand='S','2', tip_rand='G','3', tip_rand='T','4', tip_rand='D','5', '6') + Padr(Nvl(scd,''),10) TAG ord_doc
|
||||
SET ORDER TO ord_doc
|
||||
|
||||
*-- import_nota.inainte_de_do_termin() citeste variabila BARA tlIntern (linia
|
||||
*-- "Iif(tlIntern, 0, 100)"), nu This.lIntern - se bazeaza pe mostenirea PRIVATE de-a
|
||||
*-- lungul stivei de apel de la achizitie_import(tnIdSet, tlIntern), procedura reala care
|
||||
*-- ar instantia formularul (Show() modal, deci tlIntern ramane "vizibil" din metodele
|
||||
*-- formularului). Testul ocoleste achizitie_import (CREATEOBJECT direct, ca toate
|
||||
*-- celelalte teste din suita), deci tlIntern trebuie declarata explicit aici, cu ACEEASI
|
||||
*-- valoare data la CREATEOBJECT (.F. = mod import) - nu e defect de cod, e o conventie de
|
||||
*-- scop de variabila care presupune fluxul real prin achizitie_import.
|
||||
PRIVATE tlIntern
|
||||
tlIntern = .F.
|
||||
|
||||
*-- alt global de mediu real (roagest.prg la pornire) folosit de clase pentru export
|
||||
*-- fisiere temporare (XML/PDF/index) - nedeclarat pana acum pentru ca pasul Terminat
|
||||
*-- nu fusese exercitat headless inainte de stub-ul verificare.scx
|
||||
PUBLIC gcTempPath
|
||||
gcTempPath = ADDBS(SYS(2023))
|
||||
|
||||
*-- gnHandle: handle SQLCONNECT real (SQLSetprop/SQLExec native) folosit de
|
||||
*-- oscrie_in_fisiere - -1 e conventia din dbaccesscontroller.prg pt. "fara conexiune";
|
||||
*-- fara o conexiune Oracle reala, scrierea propriu-zisa in ACT nu poate fi validata aici
|
||||
PUBLIC gnHandle
|
||||
gnHandle = -1
|
||||
|
||||
*-- gnTipGest: citit bare la Do listare_nir With poAct.nnir, gnTipGest In oproceduri_listari,
|
||||
*-- dupa oscrie_in_fisiere() cu succes - 0 = gestiune normala (nu declanseaza ramurile
|
||||
*-- speciale gnTipGest=6/7 vazute in cod pentru marfa la pret de vanzare)
|
||||
PUBLIC gnTipGest
|
||||
gnTipGest = 0
|
||||
|
||||
*-- gcCondSucursala: fragment WHERE folosit la rapoarte multi-sucursala (listare_nir) -
|
||||
*-- gol = fara filtrare (o singura sucursala, ca in test_init_env.prg)
|
||||
PUBLIC gcCondSucursala
|
||||
gcCondSucursala = ''
|
||||
|
||||
DO EeLog WITH 'cursoare pregatite, CREATEOBJECT(import_nota, .F. - mod import)'
|
||||
PUBLIC goObj
|
||||
goObj = CREATEOBJECT('IMPORT_nota', .F.)
|
||||
IF VARTYPE(goObj) <> 'O'
|
||||
DO EeLog WITH 'FAIL: instantiere import_nota'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
QUIT
|
||||
ENDIF
|
||||
goObj.lDialogAratat = .T.
|
||||
goObj.oact = poAct
|
||||
goObj.lSpargeSecundare = .F.
|
||||
goObj.WindowType = 0
|
||||
goObj.Visible = .T.
|
||||
goObj.Show()
|
||||
goObj.WindowState = 2
|
||||
DOEVENTS FORCE
|
||||
|
||||
SELECT rul_temp
|
||||
ZAP
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
|
||||
PRIVATE pnAsserts, pnPass
|
||||
STORE 0 TO pnAsserts, pnPass
|
||||
|
||||
DO HarnessStep WITH 0, 'nota goala afisata, mod import (.F.)'
|
||||
|
||||
*========================= DIALOG: factura EUR + TVA DVI in RON + discount financiar =========================
|
||||
PUBLIC goDlg
|
||||
goDlg = CREATEOBJECT('import_adauga_factura', goObj)
|
||||
goDlg.cFelDoc = 'Factura'
|
||||
goDlg.nIdFdoc = 1
|
||||
goDlg.nNract = 8001
|
||||
goDlg.dDataAct = DATE()
|
||||
goDlg.nIdPartener = 601
|
||||
goDlg.cPartener = 'FURNIZOR EXTERN GMBH'
|
||||
goDlg.cExplicatia = 'Marfa import cu DVI in RON si discount'
|
||||
goDlg.nSuma = 1000
|
||||
goDlg.nSumaLei = 0
|
||||
goDlg.nCurs = 5
|
||||
goDlg.nIdValuta = 978
|
||||
goDlg.cValuta = 'EUR'
|
||||
goDlg.chkInValutaCont.Value = 1
|
||||
goDlg.chkParticipaValuta.Value = 1
|
||||
goDlg.nIdExplicatieTva = 220
|
||||
goDlg.cExplicatieTva = 'ACH. IMP. 21%'
|
||||
goDlg.nProcentTva = 21
|
||||
|
||||
*-- DVI: identitate (document vamal, partener vamal)
|
||||
goDlg.cSerieDvi = ''
|
||||
goDlg.nNractDvi = 9001
|
||||
goDlg.dDviData = DATE()
|
||||
goDlg.nIdFdocDVI = 2
|
||||
goDlg.cFelDocDvi = 'DVI'
|
||||
goDlg.nDviIdPartener = 900
|
||||
goDlg.cDviPartener = 'DIRECTIA VAMALA'
|
||||
|
||||
*-- comuta pe mod TVA DVI (radio "TVA in vama") - flux real, InteractiveChange
|
||||
goDlg.optTipTva.Value = 2
|
||||
goDlg.optTipTva.InteractiveChange()
|
||||
|
||||
*-- alegere RON pe blocul DVI, prin picker-ul REAL (mock_caut_valuta, coada FIFO cu 1 pick)
|
||||
PUBLIC goMockValuta, goMockValutaCoada
|
||||
goMockValuta = CREATEOBJECT('Custom')
|
||||
goMockValuta.AddProperty('id_valuta', 1)
|
||||
goMockValuta.AddProperty('nume_val', 'RON')
|
||||
goMockValutaCoada = CREATEOBJECT('Collection')
|
||||
LOCAL loValRon
|
||||
loValRon = CREATEOBJECT('Custom')
|
||||
loValRon.AddProperty('id_valuta', 1)
|
||||
loValRon.AddProperty('nume_val', 'RON')
|
||||
goMockValutaCoada.Add(loValRon)
|
||||
goDlg.cmdDviValuta.Click()
|
||||
=AssertStr('1-DVI valuta aleasa RON', ALLTRIM(goDlg.cDviValuta), 'RON')
|
||||
=Assert3('2-DVI curs fixat la 1 (RON)', goDlg.nDviCurs, 1)
|
||||
=Assert3('3-DVI TVA lei auto = baza_lei*21% = 1050.00', goDlg.nDviTvaLei, 1050.00)
|
||||
|
||||
*-- discount financiar (Runda32: doar baza, fara bifa) - Valid() reface imediat TVA DVI pe
|
||||
*-- baza NETA (suma-discount), fara auto-calcul separat de "TVA discount"
|
||||
goDlg.txtDiscBaza.Value = 200
|
||||
goDlg.txtDiscBaza.Valid()
|
||||
=Assert3('4-dupa discount: DVI TVA lei pe baza NETA = (5000-1000)*21% = 840.00', goDlg.nDviTvaLei, 840.00)
|
||||
|
||||
goDlg.WindowType = 0
|
||||
goDlg.Visible = .T.
|
||||
goDlg.Show()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 1, 'dialog completat: factura EUR 1000, DVI TVA RON 840.00 (baza neta), discount baza 200'
|
||||
|
||||
*-- valideaza() REAL de pe dialog (buton Termin apeleaza mereu asta primul)
|
||||
LOCAL llOkValid
|
||||
llOkValid = goDlg.valideaza()
|
||||
=Assert3('6a-dialog valideaza() reuseste', IIF(llOkValid,1,0), 1)
|
||||
|
||||
*-- toDlg construit INLINE in programul PRINCIPAL, NU prin goDlg.construieste_todlg() -
|
||||
*-- capcana l (vezi antetul mock_caut_valuta.prg): CREATEOBJECT/ADDPROPERTY nu merg corect
|
||||
*-- apelate dintr-o PROCEDURA/METODA in acest runtime headless (confirmat: crapa universal,
|
||||
*-- inclusiv pe o instanta virgina, cu eroarea 11 pe primul Addproperty din construieste_todlg;
|
||||
*-- acelasi cod, apelat din programul principal cu goDlg.* in loc de This.*, functioneaza OK).
|
||||
*-- Lista de campuri COPIATA din construieste_todlg (ointroduceri.vc2 ~6180) ca sa ramana
|
||||
*-- fidela contractului - vezi si celelalte teste motor (test_dvi_valuta_ron.prg etc.), care
|
||||
*-- folosesc acelasi tipar.
|
||||
PUBLIC goT
|
||||
goT = CREATEOBJECT('Empty')
|
||||
=ADDPROPERTY(goT,'serie_act',ALLTRIM(NVL(goDlg.cSerieAct,'')))
|
||||
=ADDPROPERTY(goT,'nract',goDlg.nNract)
|
||||
=ADDPROPERTY(goT,'dataact',goDlg.dDataAct)
|
||||
=ADDPROPERTY(goT,'fdoc',goDlg.cFelDoc)
|
||||
=ADDPROPERTY(goT,'id_fdoc',goDlg.nIdFdoc)
|
||||
=ADDPROPERTY(goT,'id_partc',goDlg.nIdPartener)
|
||||
=ADDPROPERTY(goT,'partc',goDlg.cPartener)
|
||||
=ADDPROPERTY(goT,'explicatia',ALLTRIM(NVL(goDlg.cExplicatia,'')))
|
||||
=ADDPROPERTY(goT,'suma',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,IIF(goDlg.nSumaLei<>0,goDlg.nSumaLei,ROUND(goDlg.nSuma*goDlg.nCurs,gnPC)),goDlg.nSuma))
|
||||
=ADDPROPERTY(goT,'suma_val',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,goDlg.nSuma,0))
|
||||
=ADDPROPERTY(goT,'in_valuta',goDlg.chkInValutaCont.Value)
|
||||
=ADDPROPERTY(goT,'participa_valuta',(goDlg.chkParticipaValuta.Value=1))
|
||||
=ADDPROPERTY(goT,'id_valuta',IIF(goDlg.chkInValutaCont.Value=1,goDlg.nIdValuta,0))
|
||||
=ADDPROPERTY(goT,'curs',IIF(goDlg.chkInValutaCont.Value=1,goDlg.nCurs,0))
|
||||
=ADDPROPERTY(goT,'nume_val',IIF(goDlg.chkInValutaCont.Value=1,ALLTRIM(NVL(goDlg.cValuta,'')),''))
|
||||
=ADDPROPERTY(goT,'cTipTva',IIF(goDlg.optTipTva.Value=1,'F',IIF(goDlg.optTipTva.Value=2,'D','N')))
|
||||
=ADDPROPERTY(goT,'id_jtva_coloana',goDlg.nIdExplicatieTva)
|
||||
IF goDlg.optTipTva.Value = 2
|
||||
=ADDPROPERTY(goT,'dvi_serie',CHRTRAN(ALLTRIM(NVL(goDlg.cSerieDvi,'')),CHR(34),''))
|
||||
=ADDPROPERTY(goT,'dvi_nract',goDlg.nNractDvi)
|
||||
=ADDPROPERTY(goT,'dvi_dataact',goDlg.dDviData)
|
||||
=ADDPROPERTY(goT,'dvi_id_fdoc',goDlg.nIdFdocDVI)
|
||||
=ADDPROPERTY(goT,'dvi_fdoc',goDlg.cFelDocDvi)
|
||||
=ADDPROPERTY(goT,'dvi_id_partc',goDlg.nDviIdPartener)
|
||||
=ADDPROPERTY(goT,'dvi_partc',goDlg.cDviPartener)
|
||||
=ADDPROPERTY(goT,'dvi_scc','401')
|
||||
=ADDPROPERTY(goT,'dvi_tva_lei',goDlg.nDviTvaLei)
|
||||
=ADDPROPERTY(goT,'dvi_tva_val',goDlg.nDviTvaVal)
|
||||
*-- dvi_in_valuta: LOGIC (nu numeric), derivat dupa NUME - fidel cu construieste_todlg
|
||||
=ADDPROPERTY(goT,'dvi_in_valuta',!(EMPTY(goDlg.cDviValuta) OR UPPER(ALLTRIM(goDlg.cDviValuta))=='RON'))
|
||||
=ADDPROPERTY(goT,'dvi_id_valuta',goDlg.nDviIdValuta)
|
||||
=ADDPROPERTY(goT,'dvi_curs',goDlg.nDviCurs)
|
||||
=ADDPROPERTY(goT,'dvi_nume_val',ALLTRIM(NVL(goDlg.cDviValuta,'')))
|
||||
*-- dvi_valuta_proprie: regula pe valuta EFECTIVA (fix task #9) - daca ambele parti sunt
|
||||
*-- efectiv "fara valuta" (gol sau RON), rezultat 0; altfel compara id/curs ca inainte
|
||||
=ADDPROPERTY(goT,'dvi_valuta_proprie',IIF(!(EMPTY(goDlg.cDviValuta) OR UPPER(ALLTRIM(goDlg.cDviValuta))=='RON') OR !(EMPTY(goDlg.cValuta) OR UPPER(ALLTRIM(goDlg.cValuta))=='RON'),IIF(goDlg.nDviIdValuta<>goDlg.nIdValuta OR goDlg.nDviCurs<>goDlg.nCurs,1,0),0))
|
||||
ENDIF
|
||||
=ADDPROPERTY(goT,'disc_baza_lei',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,ROUND(goDlg.nDiscBaza*goDlg.nCurs,gnPC),goDlg.nDiscBaza))
|
||||
=ADDPROPERTY(goT,'disc_baza_val',IIF(goDlg.chkInValutaCont.Value=1 AND goDlg.nCurs<>0,goDlg.nDiscBaza,0))
|
||||
|
||||
*-- "Termin" REAL: oParinte.do_adauga_factura() cu toDlg-ul construit mai sus
|
||||
LOCAL llOkAdauga
|
||||
llOkAdauga = goObj.do_adauga_factura(goT)
|
||||
=Assert3('6-do_adauga_factura(goT) reuseste (Termin)', IIF(llOkAdauga,1,0), 1)
|
||||
goDlg.Hide()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 2, 'dupa Termin pe dialog: introdc=' + TRANSFORM(RECCOUNT_ACTIVE('introdc')) + ' randuri'
|
||||
|
||||
*========================= ASSERT-URI RAND CU RAND PE introdc =========================
|
||||
LOCAL lcSccB
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 8001 AND tip_rand == 'B'
|
||||
=Assert3('7-randul B (baza factura) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
lcSccB = ALLTRIM(NVL(scc,''))
|
||||
=AssertStr('8-B.scd=371', ALLTRIM(scd), '371')
|
||||
=Assert3('9-B.suma=5000.00 (1000 EUR x curs 5)', suma, 5000.00)
|
||||
=Assert3('10-B.suma_val=1000.00', suma_val, 1000.00)
|
||||
=Assert3('11-B.in_valuta=1', NVL(in_valuta,0), 1)
|
||||
=Assert3('12-B.id_valuta=978 (EUR)', NVL(id_valuta,0), 978)
|
||||
=AssertStr('13-B.nume_val=EUR', ALLTRIM(NVL(nume_val,'')), 'EUR')
|
||||
=Assert3('14-B.id_partc=601 (furnizorul facturii)', NVL(id_partc,0), 601)
|
||||
=AssertStr('15-B.partc=FURNIZOR EXTERN GMBH', ALLTRIM(NVL(partc,'')), 'FURNIZOR EXTERN GMBH')
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 8
|
||||
DO EeLog WITH ' FAIL 8-15: randul B negasit'
|
||||
ENDIF
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('16-randul T-DVI (rand_dvi=1) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=AssertStr('17-T-DVI.scd=4426', ALLTRIM(scd), '4426')
|
||||
=AssertStr('18-T-DVI.scc=401', ALLTRIM(scc), '401')
|
||||
=Assert3('19-T-DVI.suma=840.00 (baza NETA lei x 21%, discount scazut din baza DVI)', suma, 840.00)
|
||||
=Assert3('20-T-DVI.suma_val=0 (RON)', NVL(suma_val,0), 0)
|
||||
=Assert3('21-T-DVI.in_valuta=0', NVL(in_valuta,0), 0)
|
||||
=Assert3('22-T-DVI.id_valuta=0 (normalizare fara-valuta pe randul scris)', NVL(id_valuta,0), 0)
|
||||
=Assert3('23-T-DVI.curs=0', NVL(curs,0), 0)
|
||||
=AssertStr('24-T-DVI.nume_val="" ', ALLTRIM(NVL(nume_val,'?')), '')
|
||||
=Assert3('25-T-DVI.participa_valuta=.F. (nu intra in footer valuta)', IIF(participa_valuta,1,0), 0)
|
||||
=Assert3('26-T-DVI.valuta_proprie=1 (RON <> EUR factura)', NVL(valuta_proprie,0), 1)
|
||||
=Assert3('27-T-DVI.id_partc=900 (Directia Vamala)', NVL(id_partc,0), 900)
|
||||
=AssertStr('28-T-DVI.partc=DIRECTIA VAMALA', ALLTRIM(NVL(partc,'')), 'DIRECTIA VAMALA')
|
||||
=Assert3('29-T-DVI.mod_manual=0 (TVA-ul tastat coincide cu auto-calculul pe baza neta 840.00)', NVL(mod_manual,0), 0)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 12
|
||||
DO EeLog WITH ' FAIL 17-29: randul T-DVI negasit'
|
||||
ENDIF
|
||||
|
||||
LOCAL lnCntGDoc1
|
||||
lnCntGDoc1 = 0
|
||||
SELECT introdc
|
||||
SCAN FOR nract = 8001 AND tip_rand == 'G'
|
||||
lnCntGDoc1 = lnCntGDoc1 + 1
|
||||
ENDSCAN
|
||||
=Assert3('30b-exact un singur rand G (model B/G/T, Runda32)', lnCntGDoc1, 1)
|
||||
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 8001 AND tip_rand == 'G' AND ALLTRIM(NVL(scc,'')) == '767'
|
||||
=Assert3('30-randul G (discount, 401->767) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
IF !EMPTY(lcSccB)
|
||||
=AssertStr('31-G.scd = analitic mostenit de pe creditul B', ALLTRIM(scd), lcSccB)
|
||||
ENDIF
|
||||
=Assert3('32-G.suma=+1000.00 (baza discount in lei, POZITIV)', suma, 1000.00)
|
||||
=Assert3('33-G.suma_val=+200.00 (POZITIV)', suma_val, 200.00)
|
||||
=Assert3('34-G.id_partd=601 (furnizorul facturii, de pe creditul B)', NVL(id_partd,0), 601)
|
||||
=Assert3('35-G.participa_valuta=.F.', IIF(participa_valuta,1,0), 0)
|
||||
=Assert3('36-G.cu_tva=1 (mostenit din linia de baza, runda33)', NVL(cu_tva,0), 1)
|
||||
=Assert3('37-G.ptva=21 (aceeasi cota ca linia de baza, runda33)', NVL(ptva,0), 21)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 6
|
||||
DO EeLog WITH ' FAIL 31-37: randul G negasit'
|
||||
ENDIF
|
||||
|
||||
*========================= TOTALURI SUBSOL (Runda32: total cu TVA scade discountul, =========================
|
||||
*========================= total fara TVA ramane baza integrala - D4) - inainte de a adauga =========================
|
||||
*========================= articole (document inca nespart, B ramane intreg) =========================
|
||||
=Assert3('37b-subsol: txtftvalei (fara TVA) = baza integrala 5000.00', goObj.txtftvalei.Value, 5000.00)
|
||||
=Assert3('37c-subsol: Text2 (cu TVA) = baza+TVA-discount = 5000+840-1000 = 4840.00', goObj.Text2.Value, 4840.00)
|
||||
=Assert3('37d-subsol: txtftvaval (fara TVA, valuta) = baza integrala 1000.00', goObj.txtftvaval.Value, 1000.00)
|
||||
=Assert3('37e-subsol: Text3 (cu TVA, valuta) = baza+TVA-discount = 1000+0-200 = 800.00', goObj.Text3.Value, 800.00)
|
||||
|
||||
*========================= ARTICOL prin do_adauga_articol() REAL =========================
|
||||
gcMockArtCodmat = 'ART-BULD-212'
|
||||
LOCAL llEroareArt
|
||||
llEroareArt = .F.
|
||||
TRY
|
||||
goObj.do_adauga_articol()
|
||||
CATCH TO loExcArt
|
||||
llEroareArt = .T.
|
||||
DO EeLog WITH 'EROARE do_adauga_articol ' + TRANSFORM(loExcArt.ErrorNo) + ' [' + loExcArt.Message + ']'
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
=Assert3('43-do_adauga_articol() fara eroare', IIF(llEroareArt,0,1), 1)
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-BULD-212'
|
||||
=Assert3('44-articolul BULDOEXCAVATOR adaugat in rul_temp', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
REPLACE cant WITH 1, pret_val WITH 800, pretd WITH 800, pret WITH ROUND(800*5,4), ;
|
||||
pret_lei WITH ROUND(800*5,4), cota_tva WITH 21
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO EeLog WITH ' FAIL 44: articolul nu a fost adaugat'
|
||||
ENDIF
|
||||
goObj.gridart.Refresh()
|
||||
DOEVENTS FORCE
|
||||
DO HarnessStep WITH 3, 'articol adaugat (BULDOEXCAVATOR, 800 EUR)'
|
||||
|
||||
*========================= sincronizeaza() REAL =========================
|
||||
LOCAL llEroareSync
|
||||
llEroareSync = .F.
|
||||
TRY
|
||||
goObj.sincronizeaza()
|
||||
CATCH TO loExcSync
|
||||
llEroareSync = .T.
|
||||
DO EeLog WITH 'EROARE sincronizeaza() ' + TRANSFORM(loExcSync.ErrorNo) + ' [' + loExcSync.Message + '] in ' + loExcSync.Procedure + ':' + TRANSFORM(loExcSync.LineNo)
|
||||
ENDTRY
|
||||
DOEVENTS FORCE
|
||||
=Assert3('45-sincronizeaza() fara eroare', IIF(llEroareSync,0,1), 1)
|
||||
|
||||
*-- pretul articolului neafectat de discount (discount participa_valuta=.F., exclus din baze)
|
||||
SELECT rul_temp
|
||||
LOCATE FOR ALLTRIM(codmat) == 'ART-BULD-212'
|
||||
=Assert3('46-dupa sincronizeaza(): pret_lei articol neschimbat (4000.00)', IIF(FOUND(),pret_lei,-1), 4000.00)
|
||||
|
||||
*-- randurile T-DVI si G supravietuiesc sincronizarii (nu doar la creare)
|
||||
SELECT introdc
|
||||
LOCATE FOR Nvl(rand_dvi,0) = 1
|
||||
=Assert3('47-dupa sincronizeaza(): T-DVI inca gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('48-dupa sincronizeaza(): T-DVI.suma neschimbata (840.00, baza neta, protejata de mod_manual=1)', suma, 840.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO EeLog WITH ' FAIL 48: T-DVI a disparut dupa sincronizare'
|
||||
ENDIF
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 8001 AND tip_rand == 'G' AND ALLTRIM(NVL(scc,'')) == '767'
|
||||
=Assert3('49-dupa sincronizeaza(): G inca gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('50-dupa sincronizeaza(): G.suma neschimbata (+1000.00)', suma, 1000.00)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 1
|
||||
DO EeLog WITH ' FAIL 50: G a disparut dupa sincronizare'
|
||||
ENDIF
|
||||
|
||||
*-- randul D (diferenta) - informativ, best-effort (nu e fortat de acest scenariu)
|
||||
SELECT introdc
|
||||
LOCATE FOR nract = 8001 AND tip_rand == 'D'
|
||||
IF FOUND()
|
||||
DO EeLog WITH 'INFO randul D (diferenta) exista: suma=' + TRANSFORM(suma) + ' - neafectat de discount (G exclus din bazele de calcul)'
|
||||
ELSE
|
||||
DO EeLog WITH 'INFO randul D (diferenta) nu apare in acest scenariu (numere curate, fara rotunjire reziduala) - nu e o cerinta a acestui test'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 4, 'sincronizeaza() verificat - vezi log'
|
||||
|
||||
*========================= Terminat -> scriere in actactan (stub verificare.scx, vezi handoff) =========================
|
||||
DO CreeazaActactan
|
||||
LOCAL llEroareTermin
|
||||
llEroareTermin = .F.
|
||||
TRY
|
||||
goObj.inainte_de_do_termin()
|
||||
CATCH TO loExcTermin
|
||||
llEroareTermin = .T.
|
||||
DO EeLog WITH 'EROARE inainte_de_do_termin() ' + TRANSFORM(loExcTermin.ErrorNo) + ' [' + loExcTermin.Message + '] in ' + loExcTermin.Procedure + ':' + TRANSFORM(loExcTermin.LineNo)
|
||||
ENDTRY
|
||||
=Assert3('51-inainte_de_do_termin() fara eroare (Terminat)', IIF(llEroareTermin,0,1), 1)
|
||||
|
||||
*-- Randurile in actactan sunt scrise INAINTE de Do Form verificare/oscrie_in_fisiere/
|
||||
*-- listare_nir (Scan For suma<>0 Or se_scrie=1 / Append/Gather, mult mai devreme in
|
||||
*-- metoda) - o eroare TARZIE (ex. in raportarea NIR, dupa scriere) nu invalideaza datele
|
||||
*-- deja scrise. De-aia verific actactan INDIFERENT de llEroareTermin.
|
||||
IF USED('actactan')
|
||||
DO EeLog WITH 'DIAG dump actactan dupa Terminat:'
|
||||
SELECT actactan
|
||||
SCAN
|
||||
DO EeLog WITH ' recno=' + TRANSFORM(RECNO()) + ' nract=' + TRANSFORM(nract) + ' scd=' + ALLTRIM(NVL(scd,'')) + ' scc=' + ALLTRIM(NVL(scc,'')) + ;
|
||||
' suma=' + TRANSFORM(suma) + ' suma_val=' + TRANSFORM(NVL(suma_val,0)) + ' in_valuta=?' + ' id_valuta=' + TRANSFORM(NVL(id_valuta,0)) + ;
|
||||
' id_partd=' + TRANSFORM(NVL(id_partd,0)) + ' id_partc=' + TRANSFORM(NVL(id_partc,0)) + ' partc=[' + ALLTRIM(NVL(partc,'')) + ']'
|
||||
ENDSCAN
|
||||
|
||||
=Assert3('52-actactan folosit dupa Terminat', IIF(USED('actactan'),1,0), 1)
|
||||
|
||||
*-- randul "B" (baza facturii) - sincronizeaza() redistribuie valoarea originala pe
|
||||
*-- conturile REALE ale articolelor participante (212 = contul articolului BULDOEXCAVATOR,
|
||||
*-- nu 371, placeholder-ul din sablon) - comportament PRE-EXISTENT de participare la pret,
|
||||
*-- neschimbat de F1/F2. Nu (mai) pin-uiesc contul/suma exacta (ar cere sa refac math-ul
|
||||
*-- complet de spargere pe cote) - verific doar ca valoarea facturii e reprezentata,
|
||||
*-- atribuita corect furnizorului, in EUR.
|
||||
SELECT actactan
|
||||
LOCATE FOR nract = 8001 AND ALLTRIM(NVL(scc,'')) == '401' AND suma > 0 AND NVL(id_partc,0) = 601
|
||||
=Assert3('53-actactan: cel putin un rand de baza (scc=401, furnizor) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('56-actactan randul de baza: id_valuta=978 (EUR)', NVL(id_valuta,0), 978)
|
||||
=AssertStr('57-actactan randul de baza: nume_val=EUR', ALLTRIM(NVL(nume_val,'')), 'EUR')
|
||||
=Assert3('58-actactan randul de baza: id_partc=601 (furnizorul facturii)', NVL(id_partc,0), 601)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 3
|
||||
DO EeLog WITH ' FAIL 56-58: niciun rand de baza gasit in actactan'
|
||||
ENDIF
|
||||
*-- NU verific suma totala exacta pe randurile de baza: cu un singur articol (800 EUR)
|
||||
*-- fata de baza integrala a facturii (1000 EUR), sincronizeaza() mai scrie si un rand de
|
||||
*-- diferenta/reconciliere (scd=6588) - matematica exacta de spargere pe conturi tine de
|
||||
*-- participarea la pret (pre-existenta, neschimbata de F1/F2), nu de scopul acestui test.
|
||||
|
||||
SELECT actactan
|
||||
LOCATE FOR ALLTRIM(NVL(scd,'')) == '4426' AND suma > 0
|
||||
=Assert3('59-actactan randul T-DVI (scd=4426, suma pozitiva) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('60-actactan T-DVI.suma=840.00 (baza neta)', suma, 840.00)
|
||||
=Assert3('61-actactan T-DVI.suma_val=0 (RON, in_valuta=0, necopiat)', NVL(suma_val,0), 0)
|
||||
=Assert3('62-actactan T-DVI.id_valuta=0 (RON normalizat)', NVL(id_valuta,0), 0)
|
||||
=Assert3('63-actactan T-DVI.id_partc=900 (Directia Vamala)', NVL(id_partc,0), 900)
|
||||
=AssertStr('64-actactan T-DVI.partc=DIRECTIA VAMALA', ALLTRIM(NVL(partc,'')), 'DIRECTIA VAMALA')
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 4
|
||||
DO EeLog WITH ' FAIL 60-64: randul T-DVI negasit in actactan'
|
||||
ENDIF
|
||||
|
||||
SELECT actactan
|
||||
LOCATE FOR nract = 8001 AND ALLTRIM(NVL(scc,'')) == '767'
|
||||
=Assert3('65-actactan randul G (scc=767, discount baza) gasit', IIF(FOUND(),1,0), 1)
|
||||
IF FOUND()
|
||||
=Assert3('66-actactan G.suma=+1000.00 (POZITIV)', suma, 1000.00)
|
||||
=Assert3('67-actactan G.suma_val=+200.00 (POZITIV, valuta mostenita de la B)', NVL(suma_val,0), 200.00)
|
||||
=Assert3('68-actactan G.id_partd=601 (furnizorul facturii)', NVL(id_partd,0), 601)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 3
|
||||
DO EeLog WITH ' FAIL 66-68: randul G negasit in actactan'
|
||||
ENDIF
|
||||
|
||||
*-- niciun rand fals de finalizare NIR: scd gol + scc=401 + suma=0, generat cand un rand cu_tva=0 (G) nu e exclus corect
|
||||
SELECT actactan
|
||||
LOCATE FOR EMPTY(NVL(scd,'')) AND ALLTRIM(NVL(scc,'')) == '401' AND NVL(suma,0) = 0
|
||||
=Assert3('73-niciun rand fals de finalizare NIR in actactan', IIF(FOUND(),1,0), 0)
|
||||
ELSE
|
||||
pnAsserts = pnAsserts + 16
|
||||
DO EeLog WITH ' FAIL 52-73: inainte_de_do_termin() a esuat sau actactan nu exista - assert-urile pe actactan sarite'
|
||||
ENDIF
|
||||
|
||||
DO EeLog WITH 'REZULTAT: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS'
|
||||
IF pnPass = pnAsserts
|
||||
DO EeLog WITH 'REZULTAT: PASS (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ')'
|
||||
ELSE
|
||||
DO EeLog WITH 'REZULTAT: FAIL (' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' assert-uri PASS)'
|
||||
ENDIF
|
||||
|
||||
DO HarnessStep WITH 5, 'final: ' + TRANSFORM(pnPass) + '/' + TRANSFORM(pnAsserts) + ' PASS'
|
||||
DO HarnessDone WITH 'done'
|
||||
|
||||
CATCH TO loExc
|
||||
DO EeLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
|
||||
DO HarnessDone WITH 'done-error'
|
||||
ENDTRY
|
||||
|
||||
QUIT
|
||||
|
||||
*==================================================================================
|
||||
PROCEDURE CreeazaIntrodc
|
||||
*-- Runda30 (F1/pas2): coloane NOI rand_dvi N(1), valuta_proprie N(1) fata de structura veche.
|
||||
LPARAMETERS tcAlias
|
||||
IF USED(tcAlias)
|
||||
USE IN (tcAlias)
|
||||
ENDIF
|
||||
CREATE CURSOR (tcAlias) ( ;
|
||||
id_note N(14), explicatia C(100), scd C(10), ascd C(20), scc C(10), ascc C(20), ;
|
||||
cu_tva N(1), id_set N(14), ordine N(8), in_valuta N(1), id_jtva_coloana N(14) NULL, ;
|
||||
ptva N(6,2), explicatie_tva C(50), tipjurnal C(2), taxcode N(6), paymentcode C(9), ;
|
||||
suma N(18,4), suma_val N(18,4), id_partd N(14), id_partc N(14), partd C(100), partc C(100), ;
|
||||
id_fact N(14), id_factd N(14), id_factc N(14), pereched N(14), perechec N(14), ;
|
||||
nract N(14), serie_act C(10), explicatia4 C(50), explicatia5 C(50), participa_valuta L, ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), dataact D, fdoc C(50), id_fdoc N(14), ;
|
||||
se_scrie N(1), tva_incasare N(1), doc_color N(10), doc_label C(10), tip_rand C(1), ;
|
||||
doc_key C(80), nr_doc N(8), suma_doc N(18,4), suma_doc_val N(18,4), mod_manual N(1), expl_manual N(1), ;
|
||||
scd_orig C(20), ascd_orig C(20), rand_dvi N(1), valuta_proprie N(1))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaRulTemp
|
||||
IF USED('rul_temp')
|
||||
USE IN ('rul_temp')
|
||||
ENDIF
|
||||
CREATE CURSOR rul_temp ( ;
|
||||
id_rul N(20,0), an N(4,0), luna N(2,0), cod N(20,0);
|
||||
, serie C(100), nnir N(20,0), id_articol N(10,0), denumire C(100);
|
||||
, codmat C(50), codmatf C(50), codbare C(50), um C(20);
|
||||
, id_gestiune N(5,0), nume_gestiune C(50), cgest C(20), nr_pag N(2,0);
|
||||
, gestionar C(50), comisie_receptie1 C(50), comisie_receptie2 C(50), comisie_receptie3 C(50);
|
||||
, cant N(14,3), cante N(14,3), cont C(10), acont C(20);
|
||||
, pret N(18,4), tva N(18,4), valoare N(18,4), valtva N(18,4);
|
||||
, proc_tva N(5,2), pretv N(18,4), pretvtva N(18,4), tvav N(18,4);
|
||||
, valoarev N(18,4), valtvav N(18,4), proc_tvav N(5,2), adaos N(18,4);
|
||||
, adaos_tva N(18,4), valoare_adaos N(18,4), valtva_adaos N(18,4), procent N(10,3);
|
||||
, discunitar N(18,4), discount_tva N(18,4), valoare_discount N(18,4), valtva_discount N(18,4);
|
||||
, proc_disc N(7,3), pretd N(14,4), curs N(18,4), id_valuta N(10,0);
|
||||
, nume_val C(20), id_lucrare N(20,0), nrord C(100), id_responsabil N(10,0);
|
||||
, nresp C(100), resp_marca N(18,4), dataact T, id_util N(5,0);
|
||||
, util C(30), dataora T, id_sectie N(5,0), sectie C(50);
|
||||
, csectie C(10), alcooltutun N(1,0), datain T, dataout T;
|
||||
, id_fact N(20,0), id_gestiunec N(10,0), nume_gestiunec C(50), cgestc C(20);
|
||||
, id_responsabilc N(5,0), id_reteta N(10,0), reteta C(50), nrespc C(100);
|
||||
, respc_marca N(18,4), id_set N(20,0), id_tip_rulaj N(10,0), tip_rulaj C(50);
|
||||
, id_obiect_depozit N(10,0), id_rul_aux N(10,0), nract N(20,0), serie_act C(10);
|
||||
, dataoras T, id_utils N(10,0), lot C(30), adata_expirare T;
|
||||
, id_sucursala N(5,0), sucursala C(250), id_part_rez N(10,0), part_rez C(100);
|
||||
, id_lucrare_rez N(10,0), nrord_rez C(100), subgrupa C(100), grupa C(100);
|
||||
, id_subgrupa N(5,0), id_grupa N(5,0), in_stoc N(1,0), in_crm N(1,0);
|
||||
, id_furnizor N(10,0), furnizor C(100), id_jtva_coloana N(4,0), explicatie_tva C(100);
|
||||
, taxcode N(6,0), taxname C(254), saft_procent N(18,4), codnc8 C(20);
|
||||
, id_tara_origine N(4,0), cod_tara_origine C(5), tara_origine C(50), greutate N(12,4);
|
||||
, fdoc C(30), id_fdoc N(18,4);
|
||||
, pret_lei N(18,4), pret_val N(14,4), cota_tva N(6,2))
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE CreeazaActactan
|
||||
*-- structura minima ceruta de GATHER-urile
|
||||
*-- din import_nota.inainte_de_do_termin() (Scan For suma<>0 Or se_scrie=1 / Append Blank /
|
||||
*-- Gather Name poAct + Gather Name loFact Fields ...). Fara ea, GATHER FIELDS ar da eroare
|
||||
*-- de camp inexistent inainte sa ajunga la Do Form verificare.
|
||||
IF USED('actactan')
|
||||
USE IN ('actactan')
|
||||
ENDIF
|
||||
CREATE CURSOR actactan ( ;
|
||||
id_fdoc N(14), fdoc C(50), dataact D, serie_act C(10), nract N(14), ;
|
||||
partc C(100), id_partc N(14), partd C(100), id_partd N(14), ;
|
||||
suma N(18,4), suma_val N(18,4), explicatia C(100), explicatia4 C(50), explicatia5 C(50), ;
|
||||
scd C(10), ascd C(20), scc C(10), ascc C(20), id_jtva_coloana N(14) NULL, taxcode N(6), ;
|
||||
id_valuta N(14), curs N(14,4), nume_val C(10), proc_tva N(8,4), nnir N(14), ;
|
||||
tva_incasare N(1), id_set N(14), id_gestin N(14))
|
||||
ENDPROC
|
||||
|
||||
FUNCTION RECCOUNT_ACTIVE
|
||||
LPARAMETERS tcAlias
|
||||
LOCAL lnSel, lnCnt
|
||||
lnSel = SELECT()
|
||||
SELECT (tcAlias)
|
||||
COUNT TO lnCnt FOR !DELETED()
|
||||
SELECT (lnSel)
|
||||
RETURN lnCnt
|
||||
ENDFUNC
|
||||
|
||||
PROCEDURE Assert3
|
||||
LPARAMETERS tcLabel, tuActual, tuExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF ABS(NVL(tuActual,0) - tuExpected) < 0.02
|
||||
pnPass = pnPass + 1
|
||||
DO EeLog WITH ' PASS ' + tcLabel + ' (=' + TRANSFORM(tuActual) + ')'
|
||||
ELSE
|
||||
DO EeLog WITH ' FAIL ' + tcLabel + ' (actual=' + TRANSFORM(tuActual) + ' asteptat=' + TRANSFORM(tuExpected) + ')'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE AssertStr
|
||||
LPARAMETERS tcLabel, tcActual, tcExpected
|
||||
pnAsserts = pnAsserts + 1
|
||||
IF tcActual == tcExpected
|
||||
pnPass = pnPass + 1
|
||||
DO EeLog WITH ' PASS ' + tcLabel + ' (=[' + tcActual + '])'
|
||||
ELSE
|
||||
DO EeLog WITH ' FAIL ' + tcLabel + ' (actual=[' + tcActual + '] asteptat=[' + tcExpected + '])'
|
||||
ENDIF
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE EeErr
|
||||
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
|
||||
DO EeLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE EeLog
|
||||
LPARAMETERS tcMsg
|
||||
SET SAFETY OFF
|
||||
LOCAL lcL
|
||||
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
|
||||
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
|
||||
ENDPROC
|
||||
|
||||
DEFINE CLASS dummyapp AS Custom
|
||||
PROCEDURE ReadIni
|
||||
LPARAMETERS tcSection, tcKey
|
||||
RETURN ''
|
||||
ENDPROC
|
||||
PROCEDURE WriteIni
|
||||
LPARAMETERS tcSection, tcKey, tcValue
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
DEFINE CLASS dummyexecutor AS Custom
|
||||
cEroare = ''
|
||||
PROCEDURE oExecute
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF 'VJTVA_COLOANE' $ UPPER(m.tcSql)
|
||||
DO CreeazaJtvaColoaneView WITH m.tcCursor
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF UPPER(ALLTRIM(m.tcCursor)) == 'RUL_TEMP'
|
||||
CREATE CURSOR (m.tcCursor) (denumire C(100), codmat C(30), cant N(14,3), ;
|
||||
pret_val N(18,4), pretd N(18,4), pret N(18,4), pret_lei N(18,4), cont C(10), ;
|
||||
acont C(20), serie C(30), lot C(30), adata_expirare C(10), proc_disc N(6,2), cota_tva N(6,2))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'CONFIG_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (camp_leg_prefix C(30), camp_leg_sufix C(30))
|
||||
INSERT INTO (m.tcCursor) VALUES ('', '')
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'FCONTURI_ANALITICE' $ UPPER(m.tcSql)
|
||||
CREATE CURSOR (m.tcCursor) (acont C(20))
|
||||
INSERT INTO (m.tcCursor) VALUES (IIF(TYPE('gcMockAcontCrt') = 'C', gcMockAcontCrt, ''))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VPLCONT_ANALITIC' $ UPPER(m.tcSql)
|
||||
*-- gol: niciun cont nu cere analitic in scenariul acestui test (371/401 folosite
|
||||
*-- fara analitic, ca in restul suitei - vezi verificare_note_contabile)
|
||||
CREATE CURSOR (m.tcCursor) (cont C(10), acont C(20))
|
||||
RETURN 1
|
||||
ENDIF
|
||||
IF 'VCONFIG_CONT_IREG' $ UPPER(m.tcSql)
|
||||
*-- 401 recunoscut ca si cont cu parteneri (verificare_note_contabile) - altfel
|
||||
*-- verif_part goleste id_partc/id_partd pe randurile T-DVI/G inainte de actactan
|
||||
CREATE CURSOR (m.tcCursor) (contpart C(10), fel_cont N(1), cu_inregistrari N(1), ;
|
||||
explic_cont C(100), exceptie C(10), pozitie N(1), invers N(1), gasit N(1))
|
||||
INSERT INTO (m.tcCursor) VALUES ('401', 0, 0, 'Furnizori', '', 0, 0, 0)
|
||||
RETURN 1
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oExecuta
|
||||
LPARAMETERS tcSql, tcCursor
|
||||
IF !EMPTY(m.tcCursor)
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
IF UPPER(m.tcCursor) == 'CJTVACOL4427'
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14))
|
||||
ELSE
|
||||
CREATE CURSOR (m.tcCursor) (id_temp N(1))
|
||||
ENDIF
|
||||
ENDIF
|
||||
RETURN .T.
|
||||
ENDPROC
|
||||
PROCEDURE oSelect2Value
|
||||
LPARAMETERS tcSql, toValue
|
||||
toValue = ''
|
||||
RETURN 1
|
||||
ENDPROC
|
||||
PROCEDURE oReset
|
||||
ENDPROC
|
||||
ENDDEFINE
|
||||
|
||||
PROCEDURE CreeazaJtvaColoaneView
|
||||
LPARAMETERS tcCursor
|
||||
IF USED(m.tcCursor)
|
||||
USE IN (m.tcCursor)
|
||||
ENDIF
|
||||
CREATE CURSOR (m.tcCursor) (id_jtva_coloana N(14), denumire C(100), jc N(1), jv N(1), ;
|
||||
coloana_jc C(20), coloana_jv C(20), cota_tva N(6,2), id_tva N(14) NULL, afisat N(1), ;
|
||||
id_jtva_ex N(14) NULL, id_jtva_neex N(14) NULL, ordine N(8), ;
|
||||
taxcode N(6) NULL, taxcode_neexigibil N(6) NULL, taxcode_n50 N(6) NULL, ;
|
||||
taxcode_n50_tvai N(6) NULL, taxcode_n100 N(6) NULL, taxcode_regularizare N(6) NULL, taxcode_tvai N(6) NULL)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, afisat, ordine, cota_tva) VALUES (0, '', 0, 0, 1, 0, 0)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (208, 'ACH. INT. 21%', 1, 0, 'RO21B', 21, 209, 1, 1, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (209, 'TVA ACH. INT. 21%', 1, 0, 'RO21T', 21, 1, 2, 301104)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, id_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (220, 'ACH. IMP. 21%', 1, 0, 'FO21B', 21, 221, 1, 3, 301204)
|
||||
INSERT INTO (m.tcCursor) (id_jtva_coloana, denumire, jc, jv, coloana_jc, cota_tva, afisat, ordine, taxcode) ;
|
||||
VALUES (221, 'TVA ACH. IMP. 21%', 1, 0, 'FO21T', 21, 1, 4, 301204)
|
||||
ENDPROC
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user