sync SVN r17979

This commit is contained in:
2026-08-06 00:34:35 +03:00
parent 72bf63cd04
commit c599a9c053
12 changed files with 1060 additions and 54 deletions

View File

@@ -10199,7 +10199,8 @@ DEFINE CLASS import_nota AS frm_termin_renunt OF "_frm_child.vcx"
*!* Randul D, unic pe nota (doc_key gol, nr_doc 99999999): diferenta = baza documentelor *!* Randul D, unic pe nota (doc_key gol, nr_doc 99999999): diferenta = baza documentelor
*!* care participa la pret - Suma(pret*cant) cu pretul incarcat. Cont dominant = contul de *!* care participa la pret - Suma(pret*cant) cu pretul incarcat. Cont dominant = contul de
*!* clasa 3 cu baza ABS maxima; fara clasa 3 -> clasa 2, cu contul fix 6588. Diferenta se *!* clasa 3 cu baza ABS maxima; fara clasa 3 -> clasa 2, cu contul fix 6588. Diferenta se
*!* scrie doar in lei. Antetul se mosteneste de la documentul principal. *!* scrie doar in lei, fara TVA si fara cod de taxa SAFT. Antetul se mosteneste de la
*!* documentul principal.
Local lcSel, lnMinNrDoc, lnTotalLei, lnTotalVal, lnBazaParticipa Local lcSel, lnMinNrDoc, lnTotalLei, lnTotalVal, lnBazaParticipa
Local lcContDominant, lnBazaDominantaAbs, lcScd1, lnDiferentaLei, lnDiferentaVal, lcExplicatie Local lcContDominant, lnBazaDominantaAbs, lcScd1, lnDiferentaLei, lnDiferentaVal, lcExplicatie
Local llGasitClasa3, loAntet Local llGasitClasa3, loAntet
@@ -10310,7 +10311,7 @@ DEFINE CLASS import_nota AS frm_termin_renunt OF "_frm_child.vcx"
Replace partc With '', id_partc With 0, partd With '', id_partd With 0 Replace partc With '', id_partc With 0, partd With '', id_partd With 0
Endif Endif
Replace scd With lcScd1, scc With lcContDominant, suma With lnDiferentaLei, suma_val With 0, ; Replace scd With lcScd1, scc With lcContDominant, suma With lnDiferentaLei, suma_val With 0, ;
explicatia With lcExplicatie, id_jtva_coloana With Null, ptva With 0, cu_tva With 0, ; explicatia With lcExplicatie, id_jtva_coloana With Null, taxcode With 0, ptva With 0, cu_tva With 0, ;
in_valuta With 0, participa_valuta With .F., nume_val With '', id_valuta With 0, curs With 0 in_valuta With 0, participa_valuta With .F., nume_val With '', id_valuta With 0, curs With 0
Select (lcSel) Select (lcSel)

View File

@@ -6720,6 +6720,8 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
*< OBJECTDATA: ObjPath="Grid1.Column43.Header1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="Grid1.Column43.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="Grid1.Column43.Text1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="Grid1.Column43.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="Grid1.Column43._combobox1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="Grid1.Column43._combobox1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="Grid1.Column44.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="Grid1.Column44.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="Command1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="Command1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="Gridextra1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="Gridextra1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="Command2" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="Command2" UniqueID="" Timestamp="" />
@@ -6762,6 +6764,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
*m: grid_focus_prima_coloana *m: grid_focus_prima_coloana
*m: resize_grid1 *m: resize_grid1
*m: salveazaxml *m: salveazaxml
*m: sincronizeaza_nnir
*m: updateexplicatiesaft *m: updateexplicatiesaft
*m: updateexplicatiesaftrul *m: updateexplicatiesaftrul
*m: valideaza_data *m: valideaza_data
@@ -6778,6 +6781,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
*p: lverificare *p: lverificare
*p: lvizualizare *p: lvizualizare
*p: nid_set *p: nid_set
*p: nnnirvechi
*p: noldsuma && Valoarea la intrarea in campul "Suma" *p: noldsuma && Valoarea la intrarea in campul "Suma"
*p: nprimadata *p: nprimadata
*p: nsuma && Total suma inregistrari *p: nsuma && Total suma inregistrari
@@ -6809,6 +6813,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
lvizualizare = .F. lvizualizare = .F.
Name = "frm_modific2024" Name = "frm_modific2024"
nid_set = 0 nid_set = 0
nnnirvechi = 0
noldsuma = 0 noldsuma = 0
nprimadata = 0 nprimadata = 0
nsuma = 0 nsuma = 0
@@ -7143,7 +7148,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
ADD OBJECT 'Grid1' AS grid WITH ; ADD OBJECT 'Grid1' AS grid WITH ;
Anchor = 10, ; Anchor = 10, ;
BackColor = 244,250,255, ; BackColor = 244,250,255, ;
ColumnCount = 43, ; ColumnCount = 44, ;
DeleteMark = .F., ; DeleteMark = .F., ;
FontCharSet = 238, ; FontCharSet = 238, ;
FontSize = 10, ; FontSize = 10, ;
@@ -7185,7 +7190,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column2.Width = 71, ; Column2.Width = 71, ;
Column3.Alignment = 0, ; Column3.Alignment = 0, ;
Column3.BackColor = 244,250,255, ; Column3.BackColor = 244,250,255, ;
Column3.ColumnOrder = 15, ; Column3.ColumnOrder = 16, ;
Column3.ControlSource = "fdoc", ; Column3.ControlSource = "fdoc", ;
Column3.FontCharSet = 238, ; Column3.FontCharSet = 238, ;
Column3.FontName = "Arial", ; Column3.FontName = "Arial", ;
@@ -7215,7 +7220,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column5.Width = 53, ; Column5.Width = 53, ;
Column6.Alignment = 0, ; Column6.Alignment = 0, ;
Column6.BackColor = 244,250,255, ; Column6.BackColor = 244,250,255, ;
Column6.ColumnOrder = 7, ; Column6.ColumnOrder = 8, ;
Column6.ControlSource = "partd", ; Column6.ControlSource = "partd", ;
Column6.FontCharSet = 238, ; Column6.FontCharSet = 238, ;
Column6.FontName = "Arial", ; Column6.FontName = "Arial", ;
@@ -7225,7 +7230,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column6.Width = 114, ; Column6.Width = 114, ;
Column7.Alignment = 1, ; Column7.Alignment = 1, ;
Column7.BackColor = 244,250,255, ; Column7.BackColor = 244,250,255, ;
Column7.ColumnOrder = 10, ; Column7.ColumnOrder = 11, ;
Column7.ControlSource = "scd", ; Column7.ControlSource = "scd", ;
Column7.FontCharSet = 238, ; Column7.FontCharSet = 238, ;
Column7.FontName = "Arial", ; Column7.FontName = "Arial", ;
@@ -7235,7 +7240,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column7.Width = 57, ; Column7.Width = 57, ;
Column8.Alignment = 1, ; Column8.Alignment = 1, ;
Column8.BackColor = 244,250,255, ; Column8.BackColor = 244,250,255, ;
Column8.ColumnOrder = 12, ; Column8.ColumnOrder = 13, ;
Column8.ControlSource = "scc", ; Column8.ControlSource = "scc", ;
Column8.FontCharSet = 238, ; Column8.FontCharSet = 238, ;
Column8.FontName = "Arial", ; Column8.FontName = "Arial", ;
@@ -7245,7 +7250,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column8.Width = 62, ; Column8.Width = 62, ;
Column9.Alignment = 1, ; Column9.Alignment = 1, ;
Column9.BackColor = 244,250,255, ; Column9.BackColor = 244,250,255, ;
Column9.ColumnOrder = 14, ; Column9.ColumnOrder = 15, ;
Column9.ControlSource = "suma", ; Column9.ControlSource = "suma", ;
Column9.DynamicForeColor = "IIF(SUMA>=0, RGB(0,0,0), RGB(255,0,0))", ; Column9.DynamicForeColor = "IIF(SUMA>=0, RGB(0,0,0), RGB(255,0,0))", ;
Column9.FontCharSet = 238, ; Column9.FontCharSet = 238, ;
@@ -7258,7 +7263,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column9.Width = 93, ; Column9.Width = 93, ;
Column10.Alignment = 0, ; Column10.Alignment = 0, ;
Column10.BackColor = 244,250,255, ; Column10.BackColor = 244,250,255, ;
Column10.ColumnOrder = 8, ; Column10.ColumnOrder = 9, ;
Column10.ControlSource = "partc", ; Column10.ControlSource = "partc", ;
Column10.FontCharSet = 238, ; Column10.FontCharSet = 238, ;
Column10.FontName = "Arial", ; Column10.FontName = "Arial", ;
@@ -7268,7 +7273,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column10.Width = 100, ; Column10.Width = 100, ;
Column11.Alignment = 0, ; Column11.Alignment = 0, ;
Column11.BackColor = 244,250,255, ; Column11.BackColor = 244,250,255, ;
Column11.ColumnOrder = 9, ; Column11.ColumnOrder = 10, ;
Column11.ControlSource = "explicatia", ; Column11.ControlSource = "explicatia", ;
Column11.FontCharSet = 238, ; Column11.FontCharSet = 238, ;
Column11.FontName = "Arial", ; Column11.FontName = "Arial", ;
@@ -7277,7 +7282,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column11.ReadOnly = .F., ; Column11.ReadOnly = .F., ;
Column11.Width = 77, ; Column11.Width = 77, ;
Column12.BackColor = 244,250,255, ; Column12.BackColor = 244,250,255, ;
Column12.ColumnOrder = 37, ; Column12.ColumnOrder = 38, ;
Column12.ControlSource = "cod", ; Column12.ControlSource = "cod", ;
Column12.FontCharSet = 238, ; Column12.FontCharSet = 238, ;
Column12.FontName = "Arial", ; Column12.FontName = "Arial", ;
@@ -7286,7 +7291,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column12.ReadOnly = .T., ; Column12.ReadOnly = .T., ;
Column12.Width = 52, ; Column12.Width = 52, ;
Column13.BackColor = 244,250,255, ; Column13.BackColor = 244,250,255, ;
Column13.ColumnOrder = 16, ; Column13.ColumnOrder = 17, ;
Column13.ControlSource = "pereched", ; Column13.ControlSource = "pereched", ;
Column13.FontCharSet = 238, ; Column13.FontCharSet = 238, ;
Column13.FontName = "Arial", ; Column13.FontName = "Arial", ;
@@ -7295,7 +7300,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column13.ReadOnly = .F., ; Column13.ReadOnly = .F., ;
Column13.Width = 106, ; Column13.Width = 106, ;
Column14.BackColor = 244,250,255, ; Column14.BackColor = 244,250,255, ;
Column14.ColumnOrder = 31, ; Column14.ColumnOrder = 32, ;
Column14.ControlSource = "explicatia4", ; Column14.ControlSource = "explicatia4", ;
Column14.FontCharSet = 238, ; Column14.FontCharSet = 238, ;
Column14.FontName = "Arial", ; Column14.FontName = "Arial", ;
@@ -7304,7 +7309,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column14.ReadOnly = .F., ; Column14.ReadOnly = .F., ;
Column14.Width = 120, ; Column14.Width = 120, ;
Column15.BackColor = 244,250,255, ; Column15.BackColor = 244,250,255, ;
Column15.ColumnOrder = 24, ; Column15.ColumnOrder = 25, ;
Column15.ControlSource = "nrord", ; Column15.ControlSource = "nrord", ;
Column15.FontCharSet = 238, ; Column15.FontCharSet = 238, ;
Column15.FontName = "Arial", ; Column15.FontName = "Arial", ;
@@ -7312,7 +7317,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column15.Name = "Column15", ; Column15.Name = "Column15", ;
Column15.ReadOnly = .F., ; Column15.ReadOnly = .F., ;
Column16.BackColor = 244,250,255, ; Column16.BackColor = 244,250,255, ;
Column16.ColumnOrder = 26, ; Column16.ColumnOrder = 27, ;
Column16.ControlSource = "nresp", ; Column16.ControlSource = "nresp", ;
Column16.FontCharSet = 238, ; Column16.FontCharSet = 238, ;
Column16.FontName = "Arial", ; Column16.FontName = "Arial", ;
@@ -7322,7 +7327,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column16.Name = "Column16", ; Column16.Name = "Column16", ;
Column16.ReadOnly = .F., ; Column16.ReadOnly = .F., ;
Column17.BackColor = 244,250,255, ; Column17.BackColor = 244,250,255, ;
Column17.ColumnOrder = 27, ; Column17.ColumnOrder = 28, ;
Column17.ControlSource = "dst_chlt", ; Column17.ControlSource = "dst_chlt", ;
Column17.FontCharSet = 238, ; Column17.FontCharSet = 238, ;
Column17.FontName = "Arial", ; Column17.FontName = "Arial", ;
@@ -7332,7 +7337,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column17.Name = "Column17", ; Column17.Name = "Column17", ;
Column17.ReadOnly = .F., ; Column17.ReadOnly = .F., ;
Column18.BackColor = 244,250,255, ; Column18.BackColor = 244,250,255, ;
Column18.ColumnOrder = 32, ; Column18.ColumnOrder = 33, ;
Column18.ControlSource = "explicatia5", ; Column18.ControlSource = "explicatia5", ;
Column18.FontCharSet = 238, ; Column18.FontCharSet = 238, ;
Column18.FontName = "Arial", ; Column18.FontName = "Arial", ;
@@ -7341,7 +7346,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column18.ReadOnly = .F., ; Column18.ReadOnly = .F., ;
Column18.Width = 119, ; Column18.Width = 119, ;
Column19.BackColor = 244,250,255, ; Column19.BackColor = 244,250,255, ;
Column19.ColumnOrder = 23, ; Column19.ColumnOrder = 24, ;
Column19.ControlSource = "datascad", ; Column19.ControlSource = "datascad", ;
Column19.FontCharSet = 238, ; Column19.FontCharSet = 238, ;
Column19.FontName = "Arial", ; Column19.FontName = "Arial", ;
@@ -7351,7 +7356,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column19.Visible = .T., ; Column19.Visible = .T., ;
Column19.Width = 87, ; Column19.Width = 87, ;
Column20.BackColor = 244,250,255, ; Column20.BackColor = 244,250,255, ;
Column20.ColumnOrder = 28, ; Column20.ColumnOrder = 29, ;
Column20.ControlSource = "suma_val", ; Column20.ControlSource = "suma_val", ;
Column20.FontCharSet = 238, ; Column20.FontCharSet = 238, ;
Column20.FontName = "Arial", ; Column20.FontName = "Arial", ;
@@ -7361,7 +7366,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column20.ReadOnly = .F., ; Column20.ReadOnly = .F., ;
Column20.Width = 89, ; Column20.Width = 89, ;
Column21.BackColor = 244,250,255, ; Column21.BackColor = 244,250,255, ;
Column21.ColumnOrder = 30, ; Column21.ColumnOrder = 31, ;
Column21.ControlSource = "curs", ; Column21.ControlSource = "curs", ;
Column21.FontCharSet = 238, ; Column21.FontCharSet = 238, ;
Column21.FontName = "Arial", ; Column21.FontName = "Arial", ;
@@ -7371,7 +7376,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column21.ReadOnly = .F., ; Column21.ReadOnly = .F., ;
Column21.Width = 72, ; Column21.Width = 72, ;
Column22.BackColor = 244,250,255, ; Column22.BackColor = 244,250,255, ;
Column22.ColumnOrder = 33, ; Column22.ColumnOrder = 34, ;
Column22.ControlSource = "gestin", ; Column22.ControlSource = "gestin", ;
Column22.FontCharSet = 238, ; Column22.FontCharSet = 238, ;
Column22.FontName = "Arial", ; Column22.FontName = "Arial", ;
@@ -7380,7 +7385,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column22.ReadOnly = .F., ; Column22.ReadOnly = .F., ;
Column22.Width = 116, ; Column22.Width = 116, ;
Column23.BackColor = 244,250,255, ; Column23.BackColor = 244,250,255, ;
Column23.ColumnOrder = 11, ; Column23.ColumnOrder = 12, ;
Column23.ControlSource = "ascd", ; Column23.ControlSource = "ascd", ;
Column23.FontCharSet = 238, ; Column23.FontCharSet = 238, ;
Column23.FontName = "Arial", ; Column23.FontName = "Arial", ;
@@ -7389,7 +7394,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column23.ReadOnly = .F., ; Column23.ReadOnly = .F., ;
Column23.Width = 46, ; Column23.Width = 46, ;
Column24.BackColor = 244,250,255, ; Column24.BackColor = 244,250,255, ;
Column24.ColumnOrder = 13, ; Column24.ColumnOrder = 14, ;
Column24.ControlSource = "ascc", ; Column24.ControlSource = "ascc", ;
Column24.FontCharSet = 238, ; Column24.FontCharSet = 238, ;
Column24.FontName = "Arial", ; Column24.FontName = "Arial", ;
@@ -7398,7 +7403,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column24.ReadOnly = .F., ; Column24.ReadOnly = .F., ;
Column24.Width = 48, ; Column24.Width = 48, ;
Column25.BackColor = 244,250,255, ; Column25.BackColor = 244,250,255, ;
Column25.ColumnOrder = 38, ; Column25.ColumnOrder = 39, ;
Column25.ControlSource = "id_set", ; Column25.ControlSource = "id_set", ;
Column25.FontCharSet = 238, ; Column25.FontCharSet = 238, ;
Column25.FontName = "Arial", ; Column25.FontName = "Arial", ;
@@ -7407,7 +7412,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column25.ReadOnly = .T., ; Column25.ReadOnly = .T., ;
Column25.Width = 71, ; Column25.Width = 71, ;
Column26.BackColor = 244,250,255, ; Column26.BackColor = 244,250,255, ;
Column26.ColumnOrder = 19, ; Column26.ColumnOrder = 20, ;
Column26.ControlSource = "proc_tva", ; Column26.ControlSource = "proc_tva", ;
Column26.FontCharSet = 238, ; Column26.FontCharSet = 238, ;
Column26.FontName = "Arial", ; Column26.FontName = "Arial", ;
@@ -7416,7 +7421,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column26.ReadOnly = .T., ; Column26.ReadOnly = .T., ;
Column26.Width = 54, ; Column26.Width = 54, ;
Column27.BackColor = 244,250,255, ; Column27.BackColor = 244,250,255, ;
Column27.ColumnOrder = 17, ; Column27.ColumnOrder = 18, ;
Column27.ControlSource = "perechec", ; Column27.ControlSource = "perechec", ;
Column27.FontCharSet = 238, ; Column27.FontCharSet = 238, ;
Column27.FontName = "Arial", ; Column27.FontName = "Arial", ;
@@ -7425,7 +7430,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column27.ReadOnly = .F., ; Column27.ReadOnly = .F., ;
Column27.Width = 104, ; Column27.Width = 104, ;
Column28.BackColor = 244,250,255, ; Column28.BackColor = 244,250,255, ;
Column28.ColumnOrder = 35, ; Column28.ColumnOrder = 36, ;
Column28.ControlSource = "sectie", ; Column28.ControlSource = "sectie", ;
Column28.FontCharSet = 238, ; Column28.FontCharSet = 238, ;
Column28.FontName = "Arial", ; Column28.FontName = "Arial", ;
@@ -7434,7 +7439,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column28.ReadOnly = .F., ; Column28.ReadOnly = .F., ;
Column28.Width = 88, ; Column28.Width = 88, ;
Column29.BackColor = 244,250,255, ; Column29.BackColor = 244,250,255, ;
Column29.ColumnOrder = 29, ; Column29.ColumnOrder = 30, ;
Column29.ControlSource = "nume_val", ; Column29.ControlSource = "nume_val", ;
Column29.FontCharSet = 238, ; Column29.FontCharSet = 238, ;
Column29.FontName = "Arial", ; Column29.FontName = "Arial", ;
@@ -7443,7 +7448,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column29.ReadOnly = .F., ; Column29.ReadOnly = .F., ;
Column29.Width = 79, ; Column29.Width = 79, ;
Column30.BackColor = 244,250,255, ; Column30.BackColor = 244,250,255, ;
Column30.ColumnOrder = 39, ; Column30.ColumnOrder = 40, ;
Column30.ControlSource = "id_partd", ; Column30.ControlSource = "id_partd", ;
Column30.FontCharSet = 238, ; Column30.FontCharSet = 238, ;
Column30.FontName = "Arial", ; Column30.FontName = "Arial", ;
@@ -7452,7 +7457,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column30.ReadOnly = .T., ; Column30.ReadOnly = .T., ;
Column30.Width = 55, ; Column30.Width = 55, ;
Column31.BackColor = 244,250,255, ; Column31.BackColor = 244,250,255, ;
Column31.ColumnOrder = 40, ; Column31.ColumnOrder = 41, ;
Column31.ControlSource = "id_partc", ; Column31.ControlSource = "id_partc", ;
Column31.FontCharSet = 238, ; Column31.FontCharSet = 238, ;
Column31.FontName = "Arial", ; Column31.FontName = "Arial", ;
@@ -7461,7 +7466,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column31.ReadOnly = .T., ; Column31.ReadOnly = .T., ;
Column31.Width = 55, ; Column31.Width = 55, ;
Column32.BackColor = 244,250,255, ; Column32.BackColor = 244,250,255, ;
Column32.ColumnOrder = 34, ; Column32.ColumnOrder = 35, ;
Column32.ControlSource = "gestout", ; Column32.ControlSource = "gestout", ;
Column32.FontCharSet = 238, ; Column32.FontCharSet = 238, ;
Column32.FontName = "Arial", ; Column32.FontName = "Arial", ;
@@ -7470,7 +7475,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column32.ReadOnly = .F., ; Column32.ReadOnly = .F., ;
Column32.Width = 92, ; Column32.Width = 92, ;
Column33.BackColor = 244,250,255, ; Column33.BackColor = 244,250,255, ;
Column33.ColumnOrder = 36, ; Column33.ColumnOrder = 37, ;
Column33.ControlSource = "sucursala", ; Column33.ControlSource = "sucursala", ;
Column33.FontCharSet = 238, ; Column33.FontCharSet = 238, ;
Column33.FontName = "Arial", ; Column33.FontName = "Arial", ;
@@ -7479,7 +7484,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column33.ReadOnly = .F., ; Column33.ReadOnly = .F., ;
Column33.Width = 121, ; Column33.Width = 121, ;
Column34.BackColor = 244,250,255, ; Column34.BackColor = 244,250,255, ;
Column34.ColumnOrder = 25, ; Column34.ColumnOrder = 26, ;
Column34.ControlSource = "contract", ; Column34.ControlSource = "contract", ;
Column34.FontCharSet = 238, ; Column34.FontCharSet = 238, ;
Column34.FontName = "Arial", ; Column34.FontName = "Arial", ;
@@ -7488,7 +7493,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column34.ReadOnly = .T., ; Column34.ReadOnly = .T., ;
Column34.Width = 65, ; Column34.Width = 65, ;
Column35.BackColor = 244,250,255, ; Column35.BackColor = 244,250,255, ;
Column35.ColumnOrder = 20, ; Column35.ColumnOrder = 21, ;
Column35.ControlSource = "explicatie_tva", ; Column35.ControlSource = "explicatie_tva", ;
Column35.FontCharSet = 238, ; Column35.FontCharSet = 238, ;
Column35.FontName = "Arial", ; Column35.FontName = "Arial", ;
@@ -7497,7 +7502,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column35.ReadOnly = .F., ; Column35.ReadOnly = .F., ;
Column35.Width = 136, ; Column35.Width = 136, ;
Column36.BackColor = 244,250,255, ; Column36.BackColor = 244,250,255, ;
Column36.ColumnOrder = 18, ; Column36.ColumnOrder = 19, ;
Column36.ControlSource = "cu_tva", ; Column36.ControlSource = "cu_tva", ;
Column36.FontCharSet = 238, ; Column36.FontCharSet = 238, ;
Column36.FontName = "Arial", ; Column36.FontName = "Arial", ;
@@ -7517,7 +7522,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column37.ReadOnly = .F., ; Column37.ReadOnly = .F., ;
Column37.Width = 58, ; Column37.Width = 58, ;
Column38.BackColor = 244,250,255, ; Column38.BackColor = 244,250,255, ;
Column38.ColumnOrder = 41, ; Column38.ColumnOrder = 42, ;
Column38.ControlSource = "id_fact", ; Column38.ControlSource = "id_fact", ;
Column38.FontCharSet = 238, ; Column38.FontCharSet = 238, ;
Column38.FontName = "Arial", ; Column38.FontName = "Arial", ;
@@ -7526,7 +7531,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column38.ReadOnly = .T., ; Column38.ReadOnly = .T., ;
Column38.Width = 94, ; Column38.Width = 94, ;
Column39.BackColor = 244,250,255, ; Column39.BackColor = 244,250,255, ;
Column39.ColumnOrder = 42, ; Column39.ColumnOrder = 43, ;
Column39.ControlSource = "id_factd", ; Column39.ControlSource = "id_factd", ;
Column39.FontCharSet = 238, ; Column39.FontCharSet = 238, ;
Column39.FontName = "Arial", ; Column39.FontName = "Arial", ;
@@ -7535,7 +7540,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column39.ReadOnly = .T., ; Column39.ReadOnly = .T., ;
Column39.Width = 75, ; Column39.Width = 75, ;
Column40.BackColor = 244,250,255, ; Column40.BackColor = 244,250,255, ;
Column40.ColumnOrder = 43, ; Column40.ColumnOrder = 44, ;
Column40.ControlSource = "id_factc", ; Column40.ControlSource = "id_factc", ;
Column40.FontCharSet = 238, ; Column40.FontCharSet = 238, ;
Column40.FontName = "Arial", ; Column40.FontName = "Arial", ;
@@ -7555,7 +7560,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column41.Width = 22, ; Column41.Width = 22, ;
Column42.BackColor = 244,250,255, ; Column42.BackColor = 244,250,255, ;
Column42.Bound = .F., ; Column42.Bound = .F., ;
Column42.ColumnOrder = 21, ; Column42.ColumnOrder = 22, ;
Column42.ControlSource = "Iif(Seek(tAct.taxcode,'saft_taxtable','taxcode'),saft_taxtable.taxname,'')", ; Column42.ControlSource = "Iif(Seek(tAct.taxcode,'saft_taxtable','taxcode'),saft_taxtable.taxname,'')", ;
Column42.CurrentControl = "_combobox1", ; Column42.CurrentControl = "_combobox1", ;
Column42.FontCharSet = 238, ; Column42.FontCharSet = 238, ;
@@ -7566,7 +7571,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column42.Width = 184, ; Column42.Width = 184, ;
Column43.BackColor = 244,250,255, ; Column43.BackColor = 244,250,255, ;
Column43.Bound = .F., ; Column43.Bound = .F., ;
Column43.ColumnOrder = 22, ; Column43.ColumnOrder = 23, ;
Column43.ControlSource = "Iif(Seek(tAct.paymentcode,'saft_mecanisme_plati','mcode'),saft_mecanisme_plati.paymentname,'')", ; Column43.ControlSource = "Iif(Seek(tAct.paymentcode,'saft_mecanisme_plati','mcode'),saft_mecanisme_plati.paymentname,'')", ;
Column43.CurrentControl = "_combobox1", ; Column43.CurrentControl = "_combobox1", ;
Column43.FontCharSet = 238, ; Column43.FontCharSet = 238, ;
@@ -7574,7 +7579,17 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Column43.Name = "Column43", ; Column43.Name = "Column43", ;
Column43.ReadOnly = .F., ; Column43.ReadOnly = .F., ;
Column43.Sparse = .F., ; Column43.Sparse = .F., ;
Column43.Width = 146 Column43.Width = 146, ;
Column44.Alignment = 1, ;
Column44.BackColor = 244,250,255, ;
Column44.ColumnOrder = 7, ;
Column44.ControlSource = "nnir", ;
Column44.FontCharSet = 238, ;
Column44.FontName = "Arial", ;
Column44.FontSize = 10, ;
Column44.Name = "Column44", ;
Column44.ReadOnly = .F., ;
Column44.Width = 60
*< END OBJECT: BaseClass="grid" /> *< END OBJECT: BaseClass="grid" />
ADD OBJECT 'Grid1.cAles._CHECKBOX1' AS _checkbox WITH ; ADD OBJECT 'Grid1.cAles._CHECKBOX1' AS _checkbox WITH ;
@@ -8442,6 +8457,29 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
SelectedBackColor = 49,106,197 SelectedBackColor = 49,106,197
*< END OBJECT: BaseClass="textbox" /> *< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'Grid1.Column44.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Nr. NIR", ;
FontCharSet = 238, ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1"
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'Grid1.Column44.Text1' AS textbox WITH ;
Alignment = 1, ;
BackColor = 244,250,255, ;
BorderStyle = 0, ;
FontCharSet = 238, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .F., ;
SelectedBackColor = 49,106,197
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'Grid1.Column5.Header5' AS header WITH ; ADD OBJECT 'Grid1.Column5.Header5' AS header WITH ;
Alignment = 2, ; Alignment = 2, ;
Caption = "Nr.Doc.", ; Caption = "Nr.Doc.", ;
@@ -13613,6 +13651,9 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
This.grid1.Anchor = 11 This.grid1.Anchor = 11
This.but_renunt1.Anchor = 8 This.but_renunt1.Anchor = 8
If This.nid_set = 90101
This.grid1.Column44.ReadOnly = .T.
Endif
ENDPROC ENDPROC
PROCEDURE Load PROCEDURE Load
@@ -13683,6 +13724,19 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
this.gridextra1.setup() this.gridextra1.setup()
LOCAL lcPrefFile, lcPrefFileContents, lcKey, lcPrefs
LOCAL ARRAY laNnirPrefs(1)
lcPrefFile = This.gridextra1.GetUserApplicationDataPath() + This.gridextra1.GridPreferenceFile
lcPrefFileContents = ""
IF FILE(m.lcPrefFile)
lcPrefFileContents = FILETOSTR(m.lcPrefFile)
ENDIF
lcKey = SYS(1272, This.grid1) + "("
lcPrefs = STREXTRACT(m.lcPrefFileContents, m.lcKey, ")", 1, 1)
*!* pozitioneaza coloana la prima deschidere, cat timp preferintele salvate nu o acopera
IF EMPTY(m.lcPrefs) OR ALINES(laNnirPrefs, m.lcPrefs, 7, ",") < This.grid1.ColumnCount * 2
This.grid1.Column44.ColumnOrder = 7
ENDIF
this.grid1.SetAll("dynamicbackcolor", "IIF(ALES, RGB(255,255,225), RGB(255,255,255))", "Column") this.grid1.SetAll("dynamicbackcolor", "IIF(ALES, RGB(255,255,225), RGB(255,255,255))", "Column")
This.CalculeazaTotal() This.CalculeazaTotal()
*!* 24.05.2011 ^ *!* 24.05.2011 ^
@@ -13717,6 +13771,37 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
ENDPROC ENDPROC
PROCEDURE sincronizeaza_nnir
*!* propaga NNIR-ul modificat pe toate liniile notei si pe rulajele asociate
LPARAMETERS tnNnirVechi, tnNnirNou
LOCAL lcSelect, lnRecno
IF NVL(m.tnNnirVechi, 0) = NVL(m.tnNnirNou, 0)
RETURN
ENDIF
lcSelect = SELECT()
lnRecno = RECNO('tact')
UPDATE tact SET nnir = m.tnNnirNou WHERE NVL(nnir, 0) = m.tnNnirVechi
IF USED('trul')
UPDATE trul SET nnir = m.tnNnirNou WHERE NVL(nnir, 0) = m.tnNnirVechi
IF _TALLY > 0
Thisform.pgfArticole.page1.grdRulaje.Refresh()
ENDIF
ENDIF
IF USED('trul_obinv')
UPDATE trul_obinv SET nnir = m.tnNnirNou WHERE NVL(nnir, 0) = m.tnNnirVechi
IF _TALLY > 0
Thisform.pgfArticole.page2.grdRulajeObinv.Refresh()
ENDIF
ENDIF
SELECT tact
IF BETWEEN(m.lnRecno, 1, RECCOUNT('tact'))
GO m.lnRecno
ELSE
GO TOP
ENDIF
SELECT (m.lcSelect)
ENDPROC
PROCEDURE updateexplicatiesaft PROCEDURE updateexplicatiesaft
* Daca nu este activata SAFT 406 nu fac nimic * Daca nu este activata SAFT 406 nu fac nimic
IF !m.gl406 IF !m.gl406
@@ -14201,6 +14286,10 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
.Column35.ReadOnly = .T. && cod .Column35.ReadOnly = .T. && cod
.Column25.ReadOnly = .T. && id_set .Column25.ReadOnly = .T. && id_set
ENDWITH ENDWITH
*!* pastreaza blocarea NNIR pentru notele de inventar (id_set = 90101)
IF Thisform.nid_set = 90101
This.Column44.ReadOnly = .T.
ENDIF
*!* 10.08.2011 ^ *!* 10.08.2011 ^
*!* pot selecta inregistrari din alte sucursale pentru operatiile de copiere, adaugare care *!* pot selecta inregistrari din alte sucursale pentru operatiile de copiere, adaugare care
This.cAles.ReadOnly = .F. This.cAles.ReadOnly = .F.
@@ -14674,6 +14763,19 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
thisform.cPaymentCode = ALLTRIM(tAct.paymentcode) thisform.cPaymentCode = ALLTRIM(tAct.paymentcode)
ENDPROC ENDPROC
PROCEDURE Grid1.Column44.Text1.LostFocus
Local lnNnirNou, lnNnirVechi
lnNnirVechi = thisform.nnnirvechi
lnNnirNou = NVL(tAct.nnir, 0)
Thisform.sincronizeaza_nnir(m.lnNnirVechi, m.lnNnirNou)
Thisform.nnnirvechi = m.lnNnirNou
Thisform.Grid1.Refresh()
ENDPROC
PROCEDURE Grid1.Column44.Text1.When
Thisform.nnnirvechi = NVL(tAct.nnir, 0)
ENDPROC
PROCEDURE Grid1.Column6.Text1.InteractiveChange PROCEDURE Grid1.Column6.Text1.InteractiveChange
ADDPROPERTY(this, 'lInteractiveChange') ADDPROPERTY(this, 'lInteractiveChange')
LOCAL lnIdPart LOCAL lnIdPart

View 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.

View File

@@ -76,6 +76,10 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
- Metoda noua de clasa cere `*m: nume` in `*<DefinedPropArrayMethod>`; fara ea, prima salvare - Metoda noua de clasa cere `*m: nume` in `*<DefinedPropArrayMethod>`; fara ea, prima salvare
din IDE o arunca tacut, iar refresh-ul urmator absoarbe pierderea in cache (si in .bak-uri). din IDE o arunca tacut, iar refresh-ul urmator absoarbe pierderea in cache (si in .bak-uri).
Override-urile de metode de baza (Init, Show, hook-uri) nu au nevoie de `*m:`. Override-urile de metode de baza (Init, Show, hook-uri) nu au nevoie de `*m:`.
- 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 - 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`, existente, desi corpurile PROCEDURE raman (patit pe ROAGEST: `import_adauga_factura.recalc_tva`,
`import_nota.do_adauga/do_copie/do_reface`); simptom: crash la Createobject cu `import_nota.do_adauga/do_copie/do_reface`); simptom: crash la Createobject cu

View File

@@ -0,0 +1,53 @@
# 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`).
## 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.

View 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.

View File

@@ -60,6 +60,8 @@
`0xBA` strica `a`/`t` cu caciula (`0xE3`, `0xFE`) din alte fisiere; `0xBA` strica `a`/`t` cu caciula (`0xE3`, `0xFE`) din alte fisiere;
- adaugi/rearanjezi controale pe formulare sau coloane in grid -> `conventie_ux_formulare.md`; - 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`; - 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`; - `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`; - `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`; - testare UI / prin MCP -> `testare-ui-vfp.md`, `testare-vfp-mcp.md`;

View File

@@ -3,7 +3,8 @@
Scripturile de migrare a schemei (si modelele pentru scripturi noi) sunt in Scripturile de migrare a schemei (si modelele pentru scripturi noi) sunt in
`DATABASE\SCRIPTURI_CLAR` de sub radacina suitei ROA (`gcDirMare`/`dirgen` — ex. `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`. `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. 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): Reguli confirmate de Marius (24.07.2026):

View File

@@ -12,6 +12,7 @@ a doua oara — daca a doua oara e nevoie de acelasi lucru, scrie scriptul.
| 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 | | 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` | | 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` | | 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` | | teste UI VFP | harness din `COMUN\utile\Teste` | vezi `testare-ui-vfp.md` |
Documentatia **nu** se genereaza automat si nu exista niciun hook care s-o scrie — `livrare.ps1` Documentatia **nu** se genereaza automat si nu exista niciun hook care s-o scrie — `livrare.ps1`

View File

@@ -19,7 +19,9 @@ if (-not $TranscriptPath) {
try { $TranscriptPath = (ConvertFrom-Json $stdin).transcript_path } catch { } try { $TranscriptPath = (ConvertFrom-Json $stdin).transcript_path } catch { }
} }
} }
if (-not $TranscriptPath -or -not (Test-Path $TranscriptPath)) { # la primul mesaj al unei sesiuni noi transcriptul inca nu e creat: fara fallback, ca sa nu raporteze alta sesiune
if ($TranscriptPath -and -not (Test-Path $TranscriptPath)) { exit 0 }
if (-not $TranscriptPath) {
$dir = Join-Path $env:USERPROFILE ".claude\projects\$((Get-Location).Path -replace '[:\\/]','-')" $dir = Join-Path $env:USERPROFILE ".claude\projects\$((Get-Location).Path -replace '[:\\/]','-')"
if (Test-Path $dir) { if (Test-Path $dir) {
$f = Get-ChildItem "$dir\*.jsonl" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 $f = Get-ChildItem "$dir\*.jsonl" | Sort-Object LastWriteTime -Descending | Select-Object -First 1

View File

@@ -1,6 +1,7 @@
# diag_spatiu.ps1 - diagnostic de spatiu pe serverul Oracle al unui client ROA. # diag_spatiu.ps1 - diagnostic de spatiu pe serverul Oracle al unui client ROA.
# Raspunde "cat spatiu mai am si ce ocupa unde": tablespace/datafile (cat mai poate creste), # Raspunde "cat spatiu mai am si ce ocupa unde": tablespace/datafile (cat mai poate creste),
# audit Oracle (tabele + fisiere .aud), alert log/trace/ADR, archivelog/FRA, spatiu pe discurile # plafonul de date al editiei XE, audit Oracle (tabele + fisiere .aud), alert log/trace/ADR,
# archivelog/FRA, spatiu pe discurile
# fizice ale serverului, si alti mancatori de spatiu (recyclebin, UNDO, istoric statistici/ # fizice ale serverului, si alti mancatori de spatiu (recyclebin, UNDO, istoric statistici/
# scheduler, TEMP, top segmente generic - fara nume de tabele ROA hardcodate). # scheduler, TEMP, top segmente generic - fara nume de tabele ROA hardcodate).
# STRICT READ-ONLY pe baza: doar select/agregate si UTL_FILE in mod 'R'. Actiunile de curatare # STRICT READ-ONLY pe baza: doar select/agregate si UTL_FILE in mod 'R'. Actiunile de curatare
@@ -29,6 +30,12 @@ param(
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
# praguri de alerta, aceleasi ca in PACK_DIAG_SPATIU (jobul zilnic de la clienti): tablespace-ul
# intra in atentie sub pragul absolut SAU sub procentul din maximul lui, ca sa existe timp de reactie
$PragTsMb = 2048
$PragTsPct = 15
$PragFraPct = 75
if (-not (Test-Path $SqlPlus)) { if (-not (Test-Path $SqlPlus)) {
Write-Output ('EROARE: nu gasesc sqlplus la ' + $SqlPlus) Write-Output ('EROARE: nu gasesc sqlplus la ' + $SqlPlus)
exit 1 exit 1
@@ -173,16 +180,17 @@ select a.tablespace_name,
round(a.max_bytes/1048576) mb_max, round(a.max_bytes/1048576) mb_max,
round(nvl(tf.free_bytes,0)/1048576) mb_liber, round(nvl(tf.free_bytes,0)/1048576) mb_liber,
round((nvl(tf.free_bytes,0) + a.creste_bytes)/1048576) mb_poate_creste, round((nvl(tf.free_bytes,0) + a.creste_bytes)/1048576) mb_poate_creste,
case when a.max_bytes > 0 and (nvl(tf.free_bytes,0) + a.creste_bytes) < 1048576 case when a.max_bytes > 0 and (nvl(tf.free_bytes,0) + a.creste_bytes) <
then 'ATENTIE: MAXBYTES ATINS' end stare greatest($PragTsMb * 1048576, a.max_bytes * $PragTsPct / 100)
then 'ATENTIE: APROAPE FARA LOC' end stare
from agg a, ts_free tf from agg a, ts_free tf
where a.tablespace_name = tf.tablespace_name(+) where a.tablespace_name = tf.tablespace_name(+)
order by a.tablespace_name; order by a.tablespace_name;
exit exit
"@ "@
Show-Section -Title '2. SPATIU TABLESPACE (detaliu pe datafile + cat mai poate creste)' -Text ('mb_poate_creste = liber curent + (maxbytes - alocat) - spatiul real disponibil inainte de ORA-01653, nu doar liberul de acum.' + "`n`n" + $r2.Text) Show-Section -Title '2. SPATIU TABLESPACE (detaliu pe datafile + cat mai poate creste)' -Text ('mb_poate_creste = liber curent + (maxbytes - alocat) - spatiul real disponibil inainte de ORA-01653, nu doar liberul de acum.' + "`n" + ('Prag de atentie: sub ' + $PragTsMb + ' MB ramasi sau sub ' + $PragTsPct + '% din maximul tablespace-ului.') + "`n`n" + $r2.Text)
# tablespace-urile cu maxbytes efectiv atins - top segmente acolo # tablespace-urile care au trecut pragul de atentie - top segmente acolo
$r2m = Invoke-Sql -Sql @" $r2m = Invoke-Sql -Sql @"
set pagesize 0 linesize 100 trimspool on feedback off heading off set pagesize 0 linesize 100 trimspool on feedback off heading off
with ts_free as ( with ts_free as (
@@ -196,7 +204,8 @@ select 'TS_ATENTIE|' || a.tablespace_name
from agg a, ts_free tf from agg a, ts_free tf
where a.tablespace_name = tf.tablespace_name(+) where a.tablespace_name = tf.tablespace_name(+)
and a.max_bytes > 0 and a.max_bytes > 0
and (nvl(tf.free_bytes,0) + a.creste_bytes) < 1048576; and (nvl(tf.free_bytes,0) + a.creste_bytes) <
greatest($PragTsMb * 1048576, a.max_bytes * $PragTsPct / 100);
exit exit
"@ "@
$tsProblema = @($r2m.Text -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_.StartsWith('TS_ATENTIE|') } | ForEach-Object { $_.Substring(11) } | Where-Object { $_ -match '^[A-Z0-9_]+$' }) $tsProblema = @($r2m.Text -split "`r?`n" | ForEach-Object { $_.Trim() } | Where-Object { $_.StartsWith('TS_ATENTIE|') } | ForEach-Object { $_.Substring(11) } | Where-Object { $_ -match '^[A-Z0-9_]+$' })
@@ -263,6 +272,45 @@ exit
Write-Output $rPdb.Text Write-Output $rPdb.Text
} }
# ---------- 2c. Plafonul de date al editiei XE ----------
# limita editiei, independenta de maxbytes-ul tablespace-urilor: extinderea poate fi refuzata cu
# ORA-12952 desi tablespace-ul mai are loc
Write-Output ''
Write-Output '===== 2c. PLAFON DE DATE XE ====='
$xeCritic = $false
if ($r1.Text -notmatch 'Express Edition') {
Write-Output 'Sarit - editia nu e Express Edition, nu exista plafon de date pe editie.'
} else {
$xePlafonGb = if ($verMajor -le 10) { 4 } elseif ($verMajor -eq 11) { 11 } else { 12 }
$rXe = Invoke-Sql -Sql @"
set pagesize 0 linesize 200 trimspool on feedback off heading off
select 'XEFOLOSIT|' || round(nvl(sum(f.bytes),0)/1048576, 2)
from dba_data_files f
where f.tablespace_name not in ('SYSTEM','SYSAUX')
and f.tablespace_name not in (select t.tablespace_name from dba_tablespaces t
where t.contents in ('UNDO','TEMPORARY'));
exit
"@
$xeFolositMb = $null
foreach ($line in ($rXe.Text -split "`r?`n")) {
if ($line.Trim() -match '^XEFOLOSIT\|([\d.]+)$') { $xeFolositMb = [double]$Matches[1] }
}
if ($null -eq $xeFolositMb) {
Write-Output 'Nu am putut masura datele de utilizator (dba_data_files) - vezi erorile de mai sus.'
Write-Output $rXe.Text
} else {
$xePlafonMb = $xePlafonGb * 1024
$xeLiberMb = $xePlafonMb - $xeFolositMb
$xePragMb = [math]::Max($PragTsMb, $xePlafonMb * $PragTsPct / 100)
$xeCritic = ($xeLiberMb -lt $xePragMb)
Write-Output ('Editie Express, plafon de date ' + $xePlafonGb + ' GB (masurat pe dba_data_files, fara SYSTEM/SYSAUX/UNDO/TEMP).')
Write-Output (' folosit = ' + [math]::Round($xeFolositMb/1024, 2) + ' GB liber pana la plafon = ' + [math]::Round($xeLiberMb, 0) + ' MB')
if ($xeCritic) {
Write-Output ('[ATENTIE] sub pragul de ' + [math]::Round($xePragMb, 0) + ' MB. Cand plafonul e atins, baza refuza extinderea cu ORA-12952 si nu se mai poate face nimic din baza - elibereaza date sau treci pe alta editie.')
}
}
}
# ---------- 3. Audit Oracle ---------- # ---------- 3. Audit Oracle ----------
$r3 = Invoke-Sql -Sql @" $r3 = Invoke-Sql -Sql @"
set pagesize 0 linesize 250 trimspool on feedback off heading off set pagesize 0 linesize 250 trimspool on feedback off heading off
@@ -369,12 +417,12 @@ exit
$fraCritic = $false $fraCritic = $false
foreach ($line in ($r5c.Text -split "`r?`n")) { foreach ($line in ($r5c.Text -split "`r?`n")) {
if ($line.Trim() -match '^FRAPCT\|([\d.]+)$') { if ($line.Trim() -match '^FRAPCT\|([\d.]+)$') {
if ([double]$Matches[1] -ge 80) { $fraCritic = $true } if ([double]$Matches[1] -ge $PragFraPct) { $fraCritic = $true }
} }
} }
if ($fraCritic) { if ($fraCritic) {
Write-Output '' Write-Output ''
Write-Output '[ATENTIE] FRA peste 80% pe cel putin un tip de fisier. Daca log_mode=ARCHIVELOG si FRA se umple complet, baza se blocheaza pe scriere (ORA-19809/ORA-00257).' Write-Output ('[ATENTIE] FRA peste ' + $PragFraPct + '% din spatiul alocat. Daca log_mode=ARCHIVELOG si FRA se umple complet, baza se blocheaza pe scriere (ORA-19809/ORA-00257).')
Write-Output 'Ce se poate face fara backup: marire db_recovery_file_dest_size (daca discul are loc) - imediat, fara pierdere.' Write-Output 'Ce se poate face fara backup: marire db_recovery_file_dest_size (daca discul are loc) - imediat, fara pierdere.'
Write-Output 'Ce NU se face fara backup real: sterge archivelog-uri neaplicate-la-backup ar rupe recuperarea (RMAN DELETE ARCHIVELOG ... BACKED UP 1 TIMES TO DISK, doar daca exista backup real configurat).' Write-Output 'Ce NU se face fara backup real: sterge archivelog-uri neaplicate-la-backup ar rupe recuperarea (RMAN DELETE ARCHIVELOG ... BACKED UP 1 TIMES TO DISK, doar daca exista backup real configurat).'
} }
@@ -602,12 +650,15 @@ Show-Section -Title ('7e. TOP ' + $Top + ' SEGMENTE DIN TOATA BAZA (generic, far
Write-Output '' Write-Output ''
Write-Output '===== 8. VERDICT =====' Write-Output '===== 8. VERDICT ====='
if ($tsProblema.Count -gt 0) { if ($tsProblema.Count -gt 0) {
Write-Output ('Tablespace-uri la limita (maxbytes atins): ' + ($tsProblema -join ', ') + '. Vezi sectiunea 2 pentru top segmente acolo - candidatii de curatare/crestere maxbytes sunt acolo.') Write-Output ('Tablespace-uri aproape fara loc: ' + ($tsProblema -join ', ') + '. Vezi sectiunea 2 pentru top segmente acolo - candidatii de curatare/crestere maxbytes sunt acolo.')
} else { } else {
Write-Output 'Niciun tablespace la limita de maxbytes gasit (sectiunea 2).' Write-Output ('Niciun tablespace sub pragul de atentie (' + $PragTsMb + ' MB sau ' + $PragTsPct + '% din maxim, sectiunea 2).')
}
if ($xeCritic) {
Write-Output ('Plafonul de date al editiei XE e aproape atins (sectiunea 2c) - la ORA-12952 nu se mai poate face nimic din baza. Prioritate maxima: eliberare de date sau trecere pe alta editie.')
} }
if ($fraCritic) { if ($fraCritic) {
Write-Output 'FRA peste 80% pe cel putin un tip de fisier (sectiunea 5b) - risc de blocaj pe scriere daca log_mode=ARCHIVELOG. Prioritate: verifica arhivarea/backup-ul inainte sa se umple complet.' Write-Output ('FRA peste ' + $PragFraPct + '% din spatiul alocat (sectiunea 5b) - risc de blocaj pe scriere daca log_mode=ARCHIVELOG. Prioritate: verifica arhivarea/backup-ul inainte sa se umple complet.')
} }
Write-Output 'Ordine tipica de curatare (cea mai sigura primul): fisiere .aud vechi din audit_file_dest (sters direct pe disc, fara privilegii DB) -> adrci purge pe alert/trace/incident vechi -> istoric statistici/scheduler (DBMS_STATS.PURGE_STATS / DBMS_SCHEDULER.PURGE_LOG) -> recyclebin -> resize UNDO dupa ce scade activitatea -> curatare SYS.aud$/fga_log$ sau alte tabele interne (cere SYSDBA) -> ca ultima solutie, recreare PDB (export/import).' Write-Output 'Ordine tipica de curatare (cea mai sigura primul): fisiere .aud vechi din audit_file_dest (sters direct pe disc, fara privilegii DB) -> adrci purge pe alert/trace/incident vechi -> istoric statistici/scheduler (DBMS_STATS.PURGE_STATS / DBMS_SCHEDULER.PURGE_LOG) -> recyclebin -> resize UNDO dupa ce scade activitatea -> curatare SYS.aud$/fga_log$ sau alte tabele interne (cere SYSDBA) -> ca ultima solutie, recreare PDB (export/import).'
if (-not $ConnStrSys) { if (-not $ConnStrSys) {

View File

@@ -0,0 +1,689 @@
# publicare_scripturi.ps1 - publica scripturile de migrare .sql catre clientii ROA.
# Doi pasi, exact ca formularul din tasks.exe (clase\generare_script.vcx):
# 1. import - scrie fiecare .sql in CONTAFIN_ORACLE.UPD_DATABASE de pe ROA_CENTRAL
# (script_order = 0, un rand = un script intreg); daca script_name exista deja,
# face update pe id, ca sa se republice continutul corectat;
# 2. arhiva - regenereaza database_<luna>.zip / databasen_<luna>.zip si indexii
# roa_database.xml / roa_databasen.xml in Y:\ROAUPDATE\_UPDATE.
# Continutul din arhiva se citeste INAPOI din baza, nu de pe disc, si se compara octet cu octet cu
# fisierul sursa - deci arhiva contine exact ce vor primi clientii. Optional (implicit pornit),
# arhiva generata se citeste inapoi prin zip_util_pkg, cititorul Oracle al clientului.
#
# Configurarea se citeste din settings.ini-ul lui tasks.exe (aceleasi chei pe care le foloseste
# formularul): [connection] host_database/username_database/password_database, [folder]
# script_folder (\SCRIPTURI\ -> \SCRIPTURI_CLAR\), roa_output (+ _UPDATE) si sqlplus_exe, [script]
# prefixele valide. Aliasul TNS se ia din DSN-ul ODBC numit in host_database (cheia ServerName din
# registri). Orice parametru dat explicit are prioritate fata de ini.
#
# Utilizare:
# powershell -File COMUN\utile\publicare_scripturi.ps1 -DryRun
# powershell -File COMUN\utile\publicare_scripturi.ps1 -Fisier a.sql,b.sql
# powershell -File COMUN\utile\publicare_scripturi.ps1 -Luna 2026-08
# powershell -File COMUN\utile\publicare_scripturi.ps1 -Luna 2026-08 -DoarArhiva
param(
[string[]]$Fisier,
[string]$Luna,
[string]$Settings = 'D:\PROIECTE\fox\tasks\settings.ini',
[string]$DirScripturi,
[string]$ZipPath,
[string]$BackupPath,
[switch]$DoarImport,
[switch]$DoarArhiva,
[switch]$Toate,
[switch]$FaraVerificareZip,
[switch]$DryRun,
[switch]$PastreazaTemp,
[string]$Alias,
[string]$User,
[string]$Password,
[string]$SqlPlus
)
$ErrorActionPreference = 'Stop'
Add-Type -AssemblyName System.IO.Compression.FileSystem
# octeti per bucata trimisa/citita ca hexazecimal (2 caractere per octet, sub limita de linie sqlplus)
$BUCATA = 900
# bucati per bloc PL/SQL (sursa unui bloc trebuie sa ramana sub ~64k)
$BUCATI_PER_BLOC = 15
function Scrie-Titlu {
param([string]$Text)
Write-Output ''
Write-Output ('===== ' + $Text + ' =====')
}
function Opreste {
param([string]$Mesaj)
Write-Output ''
Write-Output ('EROARE: ' + $Mesaj)
Curata-Temp
exit 1
}
function Curata-Temp {
if ($PastreazaTemp) {
if (Test-Path $TempDir) { Write-Output ('Temp pastrat: ' + $TempDir) }
return
}
if (Test-Path $TempDir) { Remove-Item -LiteralPath $TempDir -Recurse -Force -ErrorAction SilentlyContinue }
}
function Invoke-SqlPlus {
# ruleaza un script sqlplus; intoarce textul si codul de iesire (whenever sqlerror => cod <> 0)
param([string]$Sql, [string]$Nume = 'q')
$f = Join-Path $TempDir ($Nume + '_' + [guid]::NewGuid().ToString('N') + '.sql')
$antet = "whenever sqlerror exit failure rollback`r`nwhenever oserror exit failure`r`nset define off`r`nset feedback off`r`n"
[System.IO.File]::WriteAllText($f, ($antet + $Sql), [System.Text.Encoding]::ASCII)
try {
$out = & $SqlPlus -L -S $ConnStr ('@' + $f) 2>&1
$cod = $LASTEXITCODE
} catch {
$out = 'EROARE lansare sqlplus: ' + $_.Exception.Message
$cod = -1
}
if (-not $PastreazaTemp) { Remove-Item -LiteralPath $f -Force -ErrorAction SilentlyContinue }
$text = ($out | ForEach-Object { [string]$_ }) -join "`n"
[PSCustomObject]@{ Text = $text; Cod = $cod }
}
function Test-Rezultat {
param($R, [string]$Context)
if ($R.Cod -ne 0 -or $R.Text -match 'ORA-\d{5}|SP2-\d{4}|PLS-\d{5}') {
Write-Output $R.Text
Opreste ($Context + ' - sqlplus a raportat eroare (cod ' + $R.Cod + ').')
}
}
function ConvertTo-Hex {
param([byte[]]$Octeti)
if ($Octeti.Length -eq 0) { return '' }
[System.BitConverter]::ToString($Octeti).Replace('-', '')
}
function ConvertFrom-Hex {
param([string]$Hex)
$n = [int]($Hex.Length / 2)
$b = New-Object byte[] $n
for ($i = 0; $i -lt $n; $i++) { $b[$i] = [Convert]::ToByte($Hex.Substring($i * 2, 2), 16) }
,$b
}
function Citeste-Ini {
param([string]$Cale)
$ini = @{}
$sectiune = ''
foreach ($linie in [System.IO.File]::ReadAllLines($Cale, [System.Text.Encoding]::GetEncoding(1252))) {
$linie = $linie.Trim()
if (-not $linie -or $linie.StartsWith(';') -or $linie.StartsWith('#')) { continue }
if ($linie -match '^\[(.+)\]$') {
$sectiune = $Matches[1].ToLower()
if (-not $ini.ContainsKey($sectiune)) { $ini[$sectiune] = @{} }
continue
}
$p = $linie.IndexOf('=')
if ($p -lt 1 -or -not $sectiune) { continue }
$ini[$sectiune][$linie.Substring(0, $p).Trim().ToLower()] = $linie.Substring($p + 1).Trim()
}
$ini
}
function Ia-Cheie {
param($Ini, [string]$Sectiune, [string]$Cheie)
$s = $Sectiune.ToLower()
$c = $Cheie.ToLower()
if ($Ini.ContainsKey($s) -and $Ini[$s].ContainsKey($c)) { return $Ini[$s][$c] }
''
}
function Rezolva-Alias {
# numele din host_database e un DSN ODBC; aliasul TNS e in cheia ServerName a DSN-ului
param([string]$Dsn)
foreach ($radacina in @('HKCU:\SOFTWARE\ODBC\ODBC.INI', 'HKLM:\SOFTWARE\ODBC\ODBC.INI', 'HKLM:\SOFTWARE\WOW6432Node\ODBC\ODBC.INI')) {
$cale = Join-Path $radacina $Dsn
if (Test-Path $cale) {
$v = (Get-ItemProperty -Path $cale -Name 'ServerName' -ErrorAction SilentlyContinue).ServerName
if ($v) { return $v }
}
}
# nu e DSN ODBC - il tratam ca alias TNS direct
$Dsn
}
function Compara-Octeti {
param([byte[]]$A, [byte[]]$B)
if ($null -eq $A -or $null -eq $B) { return $false }
if ($A.Length -ne $B.Length) { return $false }
for ($i = 0; $i -lt $A.Length; $i++) { if ($A[$i] -ne $B[$i]) { return $false } }
$true
}
function Split-Hex {
# taie un sir hexazecimal in bucati de $BUCATA octeti
param([string]$Hex)
$l = New-Object System.Collections.ArrayList
$pas = $BUCATA * 2
for ($i = 0; $i -lt $Hex.Length; $i += $pas) {
[void]$l.Add($Hex.Substring($i, [Math]::Min($pas, $Hex.Length - $i)))
}
,$l
}
function Parseaza-NumeScript {
# <prefix>_YYYY_MM_DD_NN_<tip>.sql -> obiect cu elementele componente (ca parsescriptname din VFP)
param([string]$Cale)
$stem = [System.IO.Path]::GetFileNameWithoutExtension($Cale)
if ($stem -notmatch '^([A-Za-z]+)_(\d{4})_(\d{2})_(\d{2})_(\d+)(?:_(.+))?$') { return $null }
$an = [int]$Matches[2]; $luna = [int]$Matches[3]; $zi = [int]$Matches[4]
try { $data = Get-Date -Year $an -Month $luna -Day $zi -Hour 0 -Minute 0 -Second 0 } catch { return $null }
$tip = ''
if ($Matches[6]) { $tip = $Matches[6].ToUpper() }
[PSCustomObject]@{
Cale = $Cale
NumeScript = ($stem.ToUpper() + '.SQL')
Stem = $stem.ToUpper()
Prefix = $Matches[1].ToUpper()
Data = $data
DataYmd = $data.ToString('yyyyMMdd')
Secventa = [int]$Matches[5]
Tip = $tip
}
}
function Citeste-MetadateLuna {
# metadatele scripturilor intregi (script_order = 0) din luna, in ordinea din arhiva
param([datetime]$Inceput, [datetime]$Sfarsit)
$sql = @"
set pagesize 0 linesize 600 trimspool on heading off
select 'M|' || id || '|' || script_name || '|' || script_type || '|' || to_char(script_date,'yyyymmdd') ||
'|' || to_char(script_seq) || '|' || to_char(script_order) || '|' || nvl(script_appver,'') ||
'|' || nvl(length(script_content),0)
from upd_database
where script_order = 0
and script_date between to_date('$($Inceput.ToString('yyyyMMdd'))','yyyymmdd') and to_date('$($Sfarsit.ToString('yyyyMMdd'))','yyyymmdd')
order by script_name, id;
exit
"@
$r = Invoke-SqlPlus -Sql $sql -Nume 'meta'
Test-Rezultat -R $r -Context 'citire metadate din UPD_DATABASE'
$l = New-Object System.Collections.ArrayList
foreach ($linie in ($r.Text -split "`r?`n")) {
$linie = $linie.Trim()
if (-not $linie.StartsWith('M|')) { continue }
$c = $linie.Substring(2) -split '\|'
if ($c.Count -lt 8) { continue }
[void]$l.Add([PSCustomObject]@{
Id = [int]$c[0]
NumeScript = $c[1].Trim()
Stem = [System.IO.Path]::GetFileNameWithoutExtension($c[1].Trim())
Tip = $c[2].Trim()
DataYmd = $c[3].Trim()
Secventa = [int]$c[4]
Ordine = [int]$c[5]
AppVer = $c[6].Trim()
Lungime = [int]$c[7]
})
}
,$l
}
function Citeste-Continut {
# citeste inapoi CLOB-urile ca octeti CP1252 (hexazecimal), pentru toate id-urile date
param($Metadate)
$rezultat = @{}
if ($Metadate.Count -eq 0) { return $rezultat }
$maxBucati = 1
foreach ($m in $Metadate) {
$rezultat[$m.Id] = New-Object System.Text.StringBuilder
$b = [Math]::Ceiling($m.Lungime / $BUCATA)
if ($b -gt $maxBucati) { $maxBucati = [int]$b }
}
$toateId = @($Metadate | ForEach-Object { $_.Id })
$grupuri = New-Object System.Collections.ArrayList
for ($i = 0; $i -lt $toateId.Count; $i += 500) {
[void]$grupuri.Add('c.id in (' + (($toateId[$i..([Math]::Min($i + 499, $toateId.Count - 1))]) -join ',') + ')')
}
$ids = $grupuri -join ' or '
$sql = @"
set pagesize 0 linesize 32767 long 2000000000 longchunksize 32767 trimspool on heading off arraysize 100
select '#' || c.id || '#' || lpad(to_char(l.n),7,'0') || '#' ||
rawtohex(utl_i18n.string_to_raw(dbms_lob.substr(c.script_content, $BUCATA, (l.n-1)*$BUCATA+1), 'WE8MSWIN1252'))
from upd_database c,
(select level n from dual connect by level <= $maxBucati) l
where ($ids)
and (l.n-1)*$BUCATA < nvl(length(c.script_content),0)
order by c.id, l.n;
exit
"@
$r = Invoke-SqlPlus -Sql $sql -Nume 'citire'
Test-Rezultat -R $r -Context 'citire continut scripturi din UPD_DATABASE'
foreach ($linie in ($r.Text -split "`r?`n")) {
$linie = $linie.Trim()
if (-not $linie.StartsWith('#')) { continue }
$c = $linie.Substring(1) -split '#', 3
if ($c.Count -lt 3) { continue }
$id = [int]$c[0]
if ($rezultat.ContainsKey($id)) { [void]$rezultat[$id].Append($c[2]) }
}
$final = @{}
foreach ($k in $rezultat.Keys) { $final[$k] = ConvertFrom-Hex $rezultat[$k].ToString() }
$final
}
function Importa-Script {
# insert sau update pe script_name existent; continutul se trimite hexazecimal, bucata cu bucata
param($Info, [byte[]]$Octeti)
$hex = ConvertTo-Hex $Octeti
$bucati = Split-Hex $hex
$sb = New-Object System.Text.StringBuilder
[void]$sb.AppendLine('set serveroutput on size 1000000')
[void]$sb.AppendLine('variable b_id number')
[void]$sb.AppendLine('declare')
[void]$sb.AppendLine(' l_id number;')
[void]$sb.AppendLine('begin')
[void]$sb.AppendLine(" select max(id) into l_id from upd_database where script_name = '$($Info.NumeScript)';")
[void]$sb.AppendLine(' if l_id is null then')
[void]$sb.AppendLine(' insert into upd_database')
[void]$sb.AppendLine(' (script_name, script_type, script_date, script_seq, script_content, script_order, script_appver)')
[void]$sb.AppendLine(" values ('$($Info.NumeScript)', '$($Info.Tip)', to_date('$($Info.DataYmd)','yyyymmdd'), $($Info.Secventa), empty_clob(), 0, null)")
[void]$sb.AppendLine(' returning id into l_id;')
[void]$sb.AppendLine(' else')
[void]$sb.AppendLine(' update upd_database')
[void]$sb.AppendLine(" set script_type = '$($Info.Tip)',")
[void]$sb.AppendLine(" script_date = to_date('$($Info.DataYmd)','yyyymmdd'),")
[void]$sb.AppendLine(" script_seq = $($Info.Secventa),")
[void]$sb.AppendLine(' script_content = empty_clob(),')
[void]$sb.AppendLine(' script_order = 0,')
[void]$sb.AppendLine(' script_appver = null')
[void]$sb.AppendLine(' where id = l_id;')
[void]$sb.AppendLine(' end if;')
[void]$sb.AppendLine(' :b_id := l_id;')
[void]$sb.AppendLine(' commit;')
[void]$sb.AppendLine(" dbms_output.put_line('IDSCRIPT=' || l_id);")
[void]$sb.AppendLine('end;')
[void]$sb.AppendLine('/')
for ($i = 0; $i -lt $bucati.Count; $i += $BUCATI_PER_BLOC) {
[void]$sb.AppendLine('declare s varchar2(32767); l clob;')
[void]$sb.AppendLine('begin')
[void]$sb.AppendLine(' select script_content into l from upd_database where id = :b_id for update;')
for ($j = $i; $j -lt [Math]::Min($i + $BUCATI_PER_BLOC, $bucati.Count); $j++) {
[void]$sb.AppendLine(" s := utl_i18n.raw_to_char(hextoraw('$($bucati[$j])'),'WE8MSWIN1252'); dbms_lob.writeappend(l, length(s), s);")
}
[void]$sb.AppendLine(' commit;')
[void]$sb.AppendLine('end;')
[void]$sb.AppendLine('/')
}
[void]$sb.AppendLine('exit')
$r = Invoke-SqlPlus -Sql $sb.ToString() -Nume ('imp_' + $Info.Stem)
Test-Rezultat -R $r -Context ('import ' + $Info.NumeScript)
if ($r.Text -notmatch 'IDSCRIPT=(\d+)') { Opreste ('import ' + $Info.NumeScript + ' - nu am primit id-ul randului.') }
[int]$Matches[1]
}
function Scrie-XmlArhiva {
# acelasi format ca CURSORTOXML din genereazadatabasexml2: Windows-1252, CRLF, tab-uri,
# script_appver doar cand e completat, script_content gol (continutul e in fisierul separat)
param($Metadate, [string]$Cale)
$sb = New-Object System.Text.StringBuilder
[void]$sb.Append("<?xml version = `"1.0`" encoding=`"Windows-1252`" standalone=`"yes`"?>`r`n")
[void]$sb.Append("<VFPData>`r`n")
foreach ($m in $Metadate) {
[void]$sb.Append("`t<crsxml>`r`n")
[void]$sb.Append("`t`t<id>$($m.Id)</id>`r`n")
[void]$sb.Append("`t`t<script_name>$([System.Security.SecurityElement]::Escape($m.NumeScript))</script_name>`r`n")
[void]$sb.Append("`t`t<script_type>$([System.Security.SecurityElement]::Escape($m.Tip))</script_type>`r`n")
[void]$sb.Append("`t`t<script_date>$($m.DataYmd)</script_date>`r`n")
[void]$sb.Append("`t`t<script_seq>$($m.Secventa)</script_seq>`r`n")
[void]$sb.Append("`t`t<script_order>$($m.Ordine)</script_order>`r`n")
if ($m.AppVer) {
[void]$sb.Append("`t`t<script_appver>$([System.Security.SecurityElement]::Escape($m.AppVer))</script_appver>`r`n")
}
[void]$sb.Append("`t`t<script_extra_file>$($m.Stem).sql</script_extra_file>`r`n")
[void]$sb.Append("`t`t<script_content></script_content>`r`n")
[void]$sb.Append("`t</crsxml>`r`n")
}
[void]$sb.Append("</VFPData>`r`n")
[System.IO.File]::WriteAllText($Cale, $sb.ToString(), [System.Text.Encoding]::GetEncoding(1252))
}
function Scrie-Arhiva {
# xml-ul primul, apoi scripturile in ordinea din xml (ca ZipOpen/ZipFile din VFP)
param([string]$CaleZip, [string]$CaleXml, $Fisiere)
if (Test-Path $CaleZip) { Remove-Item -LiteralPath $CaleZip -Force }
$z = [System.IO.Compression.ZipFile]::Open($CaleZip, 'Create')
try {
[void][System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($z, $CaleXml, [System.IO.Path]::GetFileName($CaleXml), 'Optimal')
foreach ($f in $Fisiere) {
[void][System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($z, $f, [System.IO.Path]::GetFileName($f), 'Optimal')
}
} finally {
$z.Dispose()
}
}
function Scrie-IndexArhive {
# roa_database.xml / roa_databasen.xml - lista arhivelor existente, sortata dupa nume de fisier
param([string]$Prefix, [string]$Cale)
$arhive = @(Get-ChildItem -LiteralPath $ZipPath -Filter ($Prefix + '_*.zip') -File |
Where-Object { $_.Name -like ($Prefix + '_*.zip') } | Sort-Object Name)
$sb = New-Object System.Text.StringBuilder
[void]$sb.Append("<?xml version = `"1.0`" encoding=`"Windows-1252`" standalone=`"yes`"?>`r`n")
[void]$sb.Append("<VFPData>`r`n")
foreach ($a in $arhive) {
$parti = [System.IO.Path]::GetFileNameWithoutExtension($a.Name) -split '_'
if ($parti.Count -lt 3) { continue }
[void]$sb.Append("`t<crsxml>`r`n")
[void]$sb.Append("`t`t<url>|BASEPATH|/$($a.Name)</url>`r`n")
[void]$sb.Append("`t`t<data1>$($parti[1])</data1>`r`n")
[void]$sb.Append("`t`t<data2>$($parti[2])</data2>`r`n")
[void]$sb.Append("`t</crsxml>`r`n")
}
[void]$sb.Append("</VFPData>`r`n")
[System.IO.File]::WriteAllText($Cale, $sb.ToString(), [System.Text.Encoding]::GetEncoding(1252))
}
function Verifica-ArhivaPrinOracle {
# citeste arhiva inapoi cu cititorul clientului (pack_utils.decodebase64 + zip_util_pkg.get_file)
# si compara lungimea + MD5 al fiecarui fisier extras cu cel de pe disc
param([string]$CaleZip, $FisiereAsteptate)
$octeti = [System.IO.File]::ReadAllBytes($CaleZip)
$b64 = [Convert]::ToBase64String($octeti)
$sb = New-Object System.Text.StringBuilder
[void]$sb.AppendLine('set serveroutput on size unlimited')
[void]$sb.AppendLine('set pagesize 0 linesize 400 trimspool on heading off')
[void]$sb.AppendLine('variable b_z clob')
[void]$sb.AppendLine('begin dbms_lob.createtemporary(:b_z, true); end;')
[void]$sb.AppendLine('/')
# bucati multiplu de 4, ca sirul base64 sa ramana valid oriunde s-ar taia
$pas = 1920
for ($i = 0; $i -lt $b64.Length; $i += $pas * $BUCATI_PER_BLOC) {
[void]$sb.AppendLine('declare s varchar2(32767);')
[void]$sb.AppendLine('begin')
for ($j = $i; $j -lt [Math]::Min($i + $pas * $BUCATI_PER_BLOC, $b64.Length); $j += $pas) {
$bucata = $b64.Substring($j, [Math]::Min($pas, $b64.Length - $j))
[void]$sb.AppendLine(" s := '$bucata'; dbms_lob.writeappend(:b_z, length(s), s);")
}
[void]$sb.AppendLine('end;')
[void]$sb.AppendLine('/')
}
[void]$sb.AppendLine('declare')
[void]$sb.AppendLine(' l_zip blob; l_f blob;')
[void]$sb.AppendLine('begin')
[void]$sb.AppendLine(' l_zip := pack_utils.decodebase64(:b_z);')
[void]$sb.AppendLine(" dbms_output.put_line('ZIP|' || dbms_lob.getlength(l_zip));")
foreach ($f in $FisiereAsteptate) {
[void]$sb.AppendLine(" l_f := zip_util_pkg.get_file(l_zip, '$f');")
[void]$sb.AppendLine(" if l_f is null then dbms_output.put_line('LIPSA|$f');")
[void]$sb.AppendLine(" else dbms_output.put_line('FIS|$f|' || dbms_lob.getlength(l_f) || '|' || rawtohex(dbms_crypto.hash(l_f, 2))); end if;")
}
[void]$sb.AppendLine('end;')
[void]$sb.AppendLine('/')
[void]$sb.AppendLine('exit')
$r = Invoke-SqlPlus -Sql $sb.ToString() -Nume 'verifzip'
Test-Rezultat -R $r -Context ('verificare arhiva ' + [System.IO.Path]::GetFileName($CaleZip))
$citite = @{}
foreach ($linie in ($r.Text -split "`r?`n")) {
$linie = $linie.Trim()
if ($linie -match '^FIS\|([^|]+)\|(\d+)\|([0-9A-F]+)$') {
$citite[$Matches[1]] = [PSCustomObject]@{ Lungime = [int]$Matches[2]; Md5 = $Matches[3] }
} elseif ($linie -match '^LIPSA\|(.+)$') {
Opreste ('verificare arhiva - zip_util_pkg nu gaseste ' + $Matches[1] + ' in ' + $CaleZip)
}
}
$md5 = [System.Security.Cryptography.MD5]::Create()
$erori = 0
foreach ($f in $FisiereAsteptate) {
if (-not $citite.ContainsKey($f)) { Write-Output (' LIPSA ' + $f); $erori++; continue }
$local = Join-Path $TempDir $f
$b = [System.IO.File]::ReadAllBytes($local)
$h = (ConvertTo-Hex $md5.ComputeHash($b))
if ($citite[$f].Lungime -eq $b.Length -and $citite[$f].Md5 -eq $h) {
Write-Output (' ok ' + $f + ' (' + $b.Length + ' octeti)')
} else {
Write-Output (' DIFERIT ' + $f + ' - disc ' + $b.Length + '/' + $h + ', extras ' + $citite[$f].Lungime + '/' + $citite[$f].Md5)
$erori++
}
}
$md5.Dispose()
if ($erori -gt 0) { Opreste ('verificare arhiva - ' + $erori + ' fisiere nu se citesc corect prin zip_util_pkg.') }
}
# ---------- pregatire ----------
$TempDir = Join-Path $env:TEMP ('publicare_scripturi_' + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Force -Path $TempDir | Out-Null
if (-not (Test-Path -LiteralPath $Settings)) { Opreste ('nu gasesc settings.ini la ' + $Settings + ' - da caile cu -DirScripturi/-ZipPath/-Alias/-User/-Password sau alt -Settings.') }
$ini = Citeste-Ini $Settings
# parametrii dati explicit bat ini-ul
if (-not $PSBoundParameters.ContainsKey('User')) { $User = Ia-Cheie $ini 'connection' 'username_database' }
if (-not $PSBoundParameters.ContainsKey('Password')) { $Password = Ia-Cheie $ini 'connection' 'password_database' }
if (-not $PSBoundParameters.ContainsKey('Alias')) {
$dsn = Ia-Cheie $ini 'connection' 'host_database'
if ($dsn) { $Alias = Rezolva-Alias $dsn }
}
if (-not $PSBoundParameters.ContainsKey('DirScripturi')) {
$f = Ia-Cheie $ini 'folder' 'script_folder'
if ($f) { $DirScripturi = ($f.TrimEnd('\') -replace '\\SCRIPTURI$', '\SCRIPTURI_CLAR') }
}
if (-not $PSBoundParameters.ContainsKey('ZipPath')) {
$f = Ia-Cheie $ini 'folder' 'roa_output'
if ($f) { $ZipPath = (Join-Path $f '_UPDATE') }
}
if (-not $PSBoundParameters.ContainsKey('SqlPlus')) { $SqlPlus = Ia-Cheie $ini 'folder' 'sqlplus_exe' }
foreach ($p in @(@('User', $User), @('Password', $Password), @('Alias', $Alias), @('DirScripturi', $DirScripturi), @('ZipPath', $ZipPath), @('SqlPlus', $SqlPlus))) {
if (-not $p[1]) { Opreste ('lipseste ' + $p[0] + ' - nu e in ' + $Settings + ' si nu a fost dat ca parametru.') }
}
# prefixele valide (o schema tinta per prefix), pentru validarea numelor de scripturi
$prefixe = @()
if ($ini.ContainsKey('script')) { $prefixe = @($ini['script'].Values | ForEach-Object { $_.TrimEnd('_').ToUpper() }) }
if (-not (Test-Path $SqlPlus)) { Opreste ('nu gasesc sqlplus la ' + $SqlPlus) }
$env:TNS_ADMIN = Split-Path $SqlPlus -Parent
$ConnStr = $User + '/' + $Password + '@' + $Alias
if ($DoarImport -and $DoarArhiva) { Opreste '-DoarImport si -DoarArhiva se exclud reciproc.' }
# ---------- 1. ce se publica ----------
Scrie-Titlu '1. SCRIPTURI DE PUBLICAT'
$candidati = New-Object System.Collections.ArrayList
if ($Fisier) {
foreach ($f in $Fisier) {
$cale = $f
if (-not [System.IO.Path]::IsPathRooted($cale)) {
$cale = (Resolve-Path -LiteralPath $f -ErrorAction SilentlyContinue)
if (-not $cale) { Opreste ('nu gasesc fisierul ' + $f) }
$cale = $cale.Path
}
if (-not (Test-Path -LiteralPath $cale)) { Opreste ('nu gasesc fisierul ' + $cale) }
$info = Parseaza-NumeScript $cale
if (-not $info) { Opreste ('nume de script neconform (<prefix>_YYYY_MM_DD_NN_<tip>.sql): ' + $cale) }
[void]$candidati.Add($info)
}
$luni = @($candidati | ForEach-Object { $_.Data.ToString('yyyy-MM') } | Sort-Object -Unique)
if ($luni.Count -gt 1) { Opreste ('scripturile date sunt din luni diferite (' + ($luni -join ', ') + ') - ruleaza cate o luna.') }
if (-not $Luna) { $Luna = $luni[0] }
} else {
if (-not $Luna) { $Luna = (Get-Date).ToString('yyyy-MM') }
}
if ($Luna -notmatch '^(\d{4})-(\d{2})$') { Opreste ('-Luna trebuie in formatul YYYY-MM (primit: ' + $Luna + ')') }
$anLuna = [int]$Matches[1]
$lunaLuna = [int]$Matches[2]
$dataInceput = Get-Date -Year $anLuna -Month $lunaLuna -Day 1 -Hour 0 -Minute 0 -Second 0
$dataSfarsit = $dataInceput.AddMonths(1).AddDays(-1)
$etichetaLuna = $dataInceput.ToString('yyyyMMdd') + '_' + $dataSfarsit.ToString('yyyyMMdd')
$dirLuna = Join-Path (Join-Path $DirScripturi $dataInceput.ToString('yyyy')) $dataInceput.ToString('MM')
if (-not $Fisier -and -not $DoarArhiva) {
if (-not (Test-Path -LiteralPath $dirLuna)) { Opreste ('nu gasesc directorul lunii: ' + $dirLuna) }
foreach ($f in (Get-ChildItem -LiteralPath $dirLuna -Filter '*.sql' -File | Sort-Object Name)) {
$info = Parseaza-NumeScript $f.FullName
if (-not $info) { Write-Output (' [sarit] nume neconform: ' + $f.Name); continue }
[void]$candidati.Add($info)
}
}
Write-Output ('Luna: ' + $Luna + ' arhiva: ' + $etichetaLuna)
Write-Output ('Configurare: ' + $Settings)
Write-Output ('Baza: ' + $User + '@' + $Alias + ' (' + $SqlPlus + ')')
Write-Output ('Scripturi: ' + $dirLuna)
Write-Output ('Arhive: ' + $ZipPath)
foreach ($c in $candidati) {
if ($prefixe.Count -gt 0 -and $prefixe -notcontains $c.Prefix) {
Write-Output (' [atentie] prefix necunoscut "' + $c.Prefix + '" in ' + [System.IO.Path]::GetFileName($c.Cale) + ' (in ini: ' + ($prefixe -join ', ') + ')')
}
$octeti = [System.IO.File]::ReadAllBytes($c.Cale)
if ($octeti.Length -eq 0) { Opreste ('fisier gol: ' + $c.Cale) }
$text = [System.Text.Encoding]::GetEncoding(1252).GetString($octeti)
if ($text -match "(?<!`r)`n") { Opreste ('sfarsituri de linie LF in ' + $c.Cale + ' - scripturile trebuie salvate cu CRLF (parsarea pe client se face pe CHR(13)+CHR(10)).') }
Add-Member -InputObject $c -NotePropertyName Octeti -NotePropertyValue $octeti
}
# ---------- 2. starea din baza ----------
Scrie-Titlu '2. STAREA DIN UPD_DATABASE'
$metadate = Citeste-MetadateLuna -Inceput $dataInceput -Sfarsit $dataSfarsit
Write-Output ('In baza, pentru luna ' + $Luna + ': ' + $metadate.Count + ' scripturi.')
$dupaNume = @{}
foreach ($m in $metadate) { $dupaNume[$m.NumeScript] = $m }
$deImportat = New-Object System.Collections.ArrayList
if (-not $DoarArhiva) {
$existente = @($candidati | Where-Object { $dupaNume.ContainsKey($_.NumeScript) })
$continuturi = @{}
if ($existente.Count -gt 0) {
$continuturi = Citeste-Continut -Metadate @($existente | ForEach-Object { $dupaNume[$_.NumeScript] })
}
foreach ($c in $candidati) {
if (-not $dupaNume.ContainsKey($c.NumeScript)) {
Write-Output (' NOU ' + $c.NumeScript + ' (' + $c.Octeti.Length + ' octeti)')
[void]$deImportat.Add($c)
continue
}
$m = $dupaNume[$c.NumeScript]
$inBaza = $continuturi[$m.Id]
$identic = Compara-Octeti -A $inBaza -B $c.Octeti
if ($identic -and -not $Toate) {
Write-Output (' publicat ' + $c.NumeScript + ' (id ' + $m.Id + ', identic)')
} elseif ($identic) {
Write-Output (' REPUBLIC ' + $c.NumeScript + ' (id ' + $m.Id + ', identic, fortat cu -Toate)')
[void]$deImportat.Add($c)
} else {
Write-Output (' MODIFICAT ' + $c.NumeScript + ' (id ' + $m.Id + ', in baza ' + $(if ($inBaza) { $inBaza.Length } else { 0 }) + ' octeti, pe disc ' + $c.Octeti.Length + ')')
[void]$deImportat.Add($c)
}
}
}
# ---------- 3. import ----------
if (-not $DoarArhiva) {
Scrie-Titlu '3. IMPORT IN UPD_DATABASE'
if ($deImportat.Count -eq 0) {
Write-Output 'Nimic de importat - toate scripturile din luna sunt deja publicate cu acelasi continut.'
} elseif ($DryRun) {
Write-Output ('DryRun - as importa ' + $deImportat.Count + ' scripturi (vezi lista de mai sus).')
} else {
foreach ($c in $deImportat) {
$id = Importa-Script -Info $c -Octeti $c.Octeti
Write-Output (' importat ' + $c.NumeScript + ' -> id ' + $id)
}
$metadate = Citeste-MetadateLuna -Inceput $dataInceput -Sfarsit $dataSfarsit
$dupaNume = @{}
foreach ($m in $metadate) { $dupaNume[$m.NumeScript] = $m }
$verif = Citeste-Continut -Metadate @($deImportat | ForEach-Object { $dupaNume[$_.NumeScript] })
$erori = 0
foreach ($c in $deImportat) {
$m = $dupaNume[$c.NumeScript]
$inBaza = $verif[$m.Id]
if (Compara-Octeti -A $inBaza -B $c.Octeti) {
Write-Output (' verificat ' + $c.NumeScript + ' (' + $c.Octeti.Length + ' octeti, identic cu fisierul)')
} else {
Write-Output (' DIFERIT ' + $c.NumeScript + ' - continutul din baza nu coincide cu fisierul!')
$erori++
}
}
if ($erori -gt 0) { Opreste ($erori + ' scripturi nu s-au scris corect in baza - nu generez arhiva.') }
}
}
if ($DoarImport) {
Scrie-Titlu 'GATA (doar import)'
Write-Output 'Arhiva NU a fost regenerata - clientii primesc scripturile abia dupa pasul de arhiva.'
Curata-Temp
exit 0
}
# ---------- 4. arhiva lunara ----------
Scrie-Titlu '4. ARHIVA LUNARA'
if (-not (Test-Path -LiteralPath $ZipPath)) { Opreste ('nu gasesc directorul arhivelor: ' + $ZipPath) }
if ($DryRun) {
Write-Output ('DryRun - as regenera database_' + $etichetaLuna + '.zip si databasen_' + $etichetaLuna + '.zip din ' + $metadate.Count + ' scripturi.')
Curata-Temp
exit 0
}
$metadate = Citeste-MetadateLuna -Inceput $dataInceput -Sfarsit $dataSfarsit
if ($metadate.Count -eq 0) { Opreste ('nu exista scripturi in UPD_DATABASE pentru luna ' + $Luna + ' - nu am ce arhiva.') }
$continuturi = Citeste-Continut -Metadate $metadate
$fisiereSql = New-Object System.Collections.ArrayList
foreach ($m in $metadate) {
$b = $continuturi[$m.Id]
if (-not $b -or $b.Length -ne $m.Lungime) {
Opreste ('citire incompleta pentru ' + $m.NumeScript + ' (asteptat ' + $m.Lungime + ' octeti, citit ' + $(if ($b) { $b.Length } else { 0 }) + ').')
}
$numeFis = $m.Stem + '.sql'
[System.IO.File]::WriteAllBytes((Join-Path $TempDir $numeFis), $b)
[void]$fisiereSql.Add($numeFis)
}
Write-Output ('Extrase din baza: ' + $fisiereSql.Count + ' scripturi.')
$numeFisiere = @($fisiereSql)
$rezultat = @()
foreach ($prefix in @('database', 'databasen')) {
$numeXml = $prefix + '_' + $etichetaLuna + '.xml'
$caleXml = Join-Path $TempDir $numeXml
Scrie-XmlArhiva -Metadate $metadate -Cale $caleXml
$caleZip = Join-Path $TempDir ($prefix + '_' + $etichetaLuna + '.zip')
Scrie-Arhiva -CaleZip $caleZip -CaleXml $caleXml -Fisiere @($numeFisiere | ForEach-Object { Join-Path $TempDir $_ })
Write-Output ('Generat ' + [System.IO.Path]::GetFileName($caleZip) + ' (' + (Get-Item -LiteralPath $caleZip).Length + ' octeti)')
$rezultat += [PSCustomObject]@{ Zip = $caleZip; Xml = $numeXml }
}
# ---------- 5. verificare cu cititorul clientului ----------
if (-not $FaraVerificareZip) {
Scrie-Titlu '5. VERIFICARE ARHIVA PRIN ZIP_UTIL_PKG'
Verifica-ArhivaPrinOracle -CaleZip $rezultat[0].Zip -FisiereAsteptate (@($rezultat[0].Xml) + $numeFisiere)
} else {
Scrie-Titlu '5. VERIFICARE ARHIVA PRIN ZIP_UTIL_PKG'
Write-Output 'Sarit (-FaraVerificareZip).'
}
# ---------- 6. publicare in _UPDATE ----------
Scrie-Titlu '6. PUBLICARE IN _UPDATE'
if (-not $BackupPath) { $BackupPath = Join-Path $ZipPath ('_backup\' + (Get-Date).ToString('yyyyMMdd_HHmmss')) }
New-Item -ItemType Directory -Force -Path $BackupPath | Out-Null
foreach ($n in @(($rezultat | ForEach-Object { [System.IO.Path]::GetFileName($_.Zip) }) + 'roa_database.xml' + 'roa_databasen.xml')) {
$tinta = Join-Path $ZipPath $n
if (Test-Path -LiteralPath $tinta) {
Copy-Item -LiteralPath $tinta -Destination (Join-Path $BackupPath $n) -Force
Write-Output (' salvat ' + $n + ' -> ' + $BackupPath)
}
}
foreach ($r in $rezultat) {
Copy-Item -LiteralPath $r.Zip -Destination (Join-Path $ZipPath ([System.IO.Path]::GetFileName($r.Zip))) -Force
Write-Output (' publicat ' + [System.IO.Path]::GetFileName($r.Zip))
}
Scrie-IndexArhive -Prefix 'database' -Cale (Join-Path $ZipPath 'roa_database.xml')
Scrie-IndexArhive -Prefix 'databasen' -Cale (Join-Path $ZipPath 'roa_databasen.xml')
Write-Output ' publicat roa_database.xml, roa_databasen.xml'
Scrie-Titlu 'GATA'
Write-Output ('Luna ' + $Luna + ': ' + $metadate.Count + ' scripturi in arhiva, ' + $deImportat.Count + ' importate acum.')
Write-Output ('Backup-ul fisierelor inlocuite: ' + $BackupPath)
Curata-Temp
exit 0