sync SVN r17985: sursa de referinta DDL (MARIUSM_AUTO) + aliniere la origin
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Euno5AmwoFEvBTdWH8C8S
This commit is contained in:
@@ -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
|
||||
*!* 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
|
||||
*!* 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 lcContDominant, lnBazaDominantaAbs, lcScd1, lnDiferentaLei, lnDiferentaVal, lcExplicatie
|
||||
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
|
||||
Endif
|
||||
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
|
||||
|
||||
Select (lcSel)
|
||||
|
||||
@@ -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.Text1" 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="Gridextra1" 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: resize_grid1
|
||||
*m: salveazaxml
|
||||
*m: sincronizeaza_nnir
|
||||
*m: updateexplicatiesaft
|
||||
*m: updateexplicatiesaftrul
|
||||
*m: valideaza_data
|
||||
@@ -6778,6 +6781,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
*p: lverificare
|
||||
*p: lvizualizare
|
||||
*p: nid_set
|
||||
*p: nnnirvechi
|
||||
*p: noldsuma && Valoarea la intrarea in campul "Suma"
|
||||
*p: nprimadata
|
||||
*p: nsuma && Total suma inregistrari
|
||||
@@ -6809,6 +6813,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
lvizualizare = .F.
|
||||
Name = "frm_modific2024"
|
||||
nid_set = 0
|
||||
nnnirvechi = 0
|
||||
noldsuma = 0
|
||||
nprimadata = 0
|
||||
nsuma = 0
|
||||
@@ -7143,7 +7148,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
ADD OBJECT 'Grid1' AS grid WITH ;
|
||||
Anchor = 10, ;
|
||||
BackColor = 244,250,255, ;
|
||||
ColumnCount = 43, ;
|
||||
ColumnCount = 44, ;
|
||||
DeleteMark = .F., ;
|
||||
FontCharSet = 238, ;
|
||||
FontSize = 10, ;
|
||||
@@ -7185,7 +7190,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column2.Width = 71, ;
|
||||
Column3.Alignment = 0, ;
|
||||
Column3.BackColor = 244,250,255, ;
|
||||
Column3.ColumnOrder = 15, ;
|
||||
Column3.ColumnOrder = 16, ;
|
||||
Column3.ControlSource = "fdoc", ;
|
||||
Column3.FontCharSet = 238, ;
|
||||
Column3.FontName = "Arial", ;
|
||||
@@ -7215,7 +7220,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column5.Width = 53, ;
|
||||
Column6.Alignment = 0, ;
|
||||
Column6.BackColor = 244,250,255, ;
|
||||
Column6.ColumnOrder = 7, ;
|
||||
Column6.ColumnOrder = 8, ;
|
||||
Column6.ControlSource = "partd", ;
|
||||
Column6.FontCharSet = 238, ;
|
||||
Column6.FontName = "Arial", ;
|
||||
@@ -7225,7 +7230,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column6.Width = 114, ;
|
||||
Column7.Alignment = 1, ;
|
||||
Column7.BackColor = 244,250,255, ;
|
||||
Column7.ColumnOrder = 10, ;
|
||||
Column7.ColumnOrder = 11, ;
|
||||
Column7.ControlSource = "scd", ;
|
||||
Column7.FontCharSet = 238, ;
|
||||
Column7.FontName = "Arial", ;
|
||||
@@ -7235,7 +7240,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column7.Width = 57, ;
|
||||
Column8.Alignment = 1, ;
|
||||
Column8.BackColor = 244,250,255, ;
|
||||
Column8.ColumnOrder = 12, ;
|
||||
Column8.ColumnOrder = 13, ;
|
||||
Column8.ControlSource = "scc", ;
|
||||
Column8.FontCharSet = 238, ;
|
||||
Column8.FontName = "Arial", ;
|
||||
@@ -7245,7 +7250,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column8.Width = 62, ;
|
||||
Column9.Alignment = 1, ;
|
||||
Column9.BackColor = 244,250,255, ;
|
||||
Column9.ColumnOrder = 14, ;
|
||||
Column9.ColumnOrder = 15, ;
|
||||
Column9.ControlSource = "suma", ;
|
||||
Column9.DynamicForeColor = "IIF(SUMA>=0, RGB(0,0,0), RGB(255,0,0))", ;
|
||||
Column9.FontCharSet = 238, ;
|
||||
@@ -7258,7 +7263,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column9.Width = 93, ;
|
||||
Column10.Alignment = 0, ;
|
||||
Column10.BackColor = 244,250,255, ;
|
||||
Column10.ColumnOrder = 8, ;
|
||||
Column10.ColumnOrder = 9, ;
|
||||
Column10.ControlSource = "partc", ;
|
||||
Column10.FontCharSet = 238, ;
|
||||
Column10.FontName = "Arial", ;
|
||||
@@ -7268,7 +7273,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column10.Width = 100, ;
|
||||
Column11.Alignment = 0, ;
|
||||
Column11.BackColor = 244,250,255, ;
|
||||
Column11.ColumnOrder = 9, ;
|
||||
Column11.ColumnOrder = 10, ;
|
||||
Column11.ControlSource = "explicatia", ;
|
||||
Column11.FontCharSet = 238, ;
|
||||
Column11.FontName = "Arial", ;
|
||||
@@ -7277,7 +7282,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column11.ReadOnly = .F., ;
|
||||
Column11.Width = 77, ;
|
||||
Column12.BackColor = 244,250,255, ;
|
||||
Column12.ColumnOrder = 37, ;
|
||||
Column12.ColumnOrder = 38, ;
|
||||
Column12.ControlSource = "cod", ;
|
||||
Column12.FontCharSet = 238, ;
|
||||
Column12.FontName = "Arial", ;
|
||||
@@ -7286,7 +7291,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column12.ReadOnly = .T., ;
|
||||
Column12.Width = 52, ;
|
||||
Column13.BackColor = 244,250,255, ;
|
||||
Column13.ColumnOrder = 16, ;
|
||||
Column13.ColumnOrder = 17, ;
|
||||
Column13.ControlSource = "pereched", ;
|
||||
Column13.FontCharSet = 238, ;
|
||||
Column13.FontName = "Arial", ;
|
||||
@@ -7295,7 +7300,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column13.ReadOnly = .F., ;
|
||||
Column13.Width = 106, ;
|
||||
Column14.BackColor = 244,250,255, ;
|
||||
Column14.ColumnOrder = 31, ;
|
||||
Column14.ColumnOrder = 32, ;
|
||||
Column14.ControlSource = "explicatia4", ;
|
||||
Column14.FontCharSet = 238, ;
|
||||
Column14.FontName = "Arial", ;
|
||||
@@ -7304,7 +7309,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column14.ReadOnly = .F., ;
|
||||
Column14.Width = 120, ;
|
||||
Column15.BackColor = 244,250,255, ;
|
||||
Column15.ColumnOrder = 24, ;
|
||||
Column15.ColumnOrder = 25, ;
|
||||
Column15.ControlSource = "nrord", ;
|
||||
Column15.FontCharSet = 238, ;
|
||||
Column15.FontName = "Arial", ;
|
||||
@@ -7312,7 +7317,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column15.Name = "Column15", ;
|
||||
Column15.ReadOnly = .F., ;
|
||||
Column16.BackColor = 244,250,255, ;
|
||||
Column16.ColumnOrder = 26, ;
|
||||
Column16.ColumnOrder = 27, ;
|
||||
Column16.ControlSource = "nresp", ;
|
||||
Column16.FontCharSet = 238, ;
|
||||
Column16.FontName = "Arial", ;
|
||||
@@ -7322,7 +7327,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column16.Name = "Column16", ;
|
||||
Column16.ReadOnly = .F., ;
|
||||
Column17.BackColor = 244,250,255, ;
|
||||
Column17.ColumnOrder = 27, ;
|
||||
Column17.ColumnOrder = 28, ;
|
||||
Column17.ControlSource = "dst_chlt", ;
|
||||
Column17.FontCharSet = 238, ;
|
||||
Column17.FontName = "Arial", ;
|
||||
@@ -7332,7 +7337,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column17.Name = "Column17", ;
|
||||
Column17.ReadOnly = .F., ;
|
||||
Column18.BackColor = 244,250,255, ;
|
||||
Column18.ColumnOrder = 32, ;
|
||||
Column18.ColumnOrder = 33, ;
|
||||
Column18.ControlSource = "explicatia5", ;
|
||||
Column18.FontCharSet = 238, ;
|
||||
Column18.FontName = "Arial", ;
|
||||
@@ -7341,7 +7346,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column18.ReadOnly = .F., ;
|
||||
Column18.Width = 119, ;
|
||||
Column19.BackColor = 244,250,255, ;
|
||||
Column19.ColumnOrder = 23, ;
|
||||
Column19.ColumnOrder = 24, ;
|
||||
Column19.ControlSource = "datascad", ;
|
||||
Column19.FontCharSet = 238, ;
|
||||
Column19.FontName = "Arial", ;
|
||||
@@ -7351,7 +7356,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column19.Visible = .T., ;
|
||||
Column19.Width = 87, ;
|
||||
Column20.BackColor = 244,250,255, ;
|
||||
Column20.ColumnOrder = 28, ;
|
||||
Column20.ColumnOrder = 29, ;
|
||||
Column20.ControlSource = "suma_val", ;
|
||||
Column20.FontCharSet = 238, ;
|
||||
Column20.FontName = "Arial", ;
|
||||
@@ -7361,7 +7366,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column20.ReadOnly = .F., ;
|
||||
Column20.Width = 89, ;
|
||||
Column21.BackColor = 244,250,255, ;
|
||||
Column21.ColumnOrder = 30, ;
|
||||
Column21.ColumnOrder = 31, ;
|
||||
Column21.ControlSource = "curs", ;
|
||||
Column21.FontCharSet = 238, ;
|
||||
Column21.FontName = "Arial", ;
|
||||
@@ -7371,7 +7376,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column21.ReadOnly = .F., ;
|
||||
Column21.Width = 72, ;
|
||||
Column22.BackColor = 244,250,255, ;
|
||||
Column22.ColumnOrder = 33, ;
|
||||
Column22.ColumnOrder = 34, ;
|
||||
Column22.ControlSource = "gestin", ;
|
||||
Column22.FontCharSet = 238, ;
|
||||
Column22.FontName = "Arial", ;
|
||||
@@ -7380,7 +7385,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column22.ReadOnly = .F., ;
|
||||
Column22.Width = 116, ;
|
||||
Column23.BackColor = 244,250,255, ;
|
||||
Column23.ColumnOrder = 11, ;
|
||||
Column23.ColumnOrder = 12, ;
|
||||
Column23.ControlSource = "ascd", ;
|
||||
Column23.FontCharSet = 238, ;
|
||||
Column23.FontName = "Arial", ;
|
||||
@@ -7389,7 +7394,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column23.ReadOnly = .F., ;
|
||||
Column23.Width = 46, ;
|
||||
Column24.BackColor = 244,250,255, ;
|
||||
Column24.ColumnOrder = 13, ;
|
||||
Column24.ColumnOrder = 14, ;
|
||||
Column24.ControlSource = "ascc", ;
|
||||
Column24.FontCharSet = 238, ;
|
||||
Column24.FontName = "Arial", ;
|
||||
@@ -7398,7 +7403,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column24.ReadOnly = .F., ;
|
||||
Column24.Width = 48, ;
|
||||
Column25.BackColor = 244,250,255, ;
|
||||
Column25.ColumnOrder = 38, ;
|
||||
Column25.ColumnOrder = 39, ;
|
||||
Column25.ControlSource = "id_set", ;
|
||||
Column25.FontCharSet = 238, ;
|
||||
Column25.FontName = "Arial", ;
|
||||
@@ -7407,7 +7412,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column25.ReadOnly = .T., ;
|
||||
Column25.Width = 71, ;
|
||||
Column26.BackColor = 244,250,255, ;
|
||||
Column26.ColumnOrder = 19, ;
|
||||
Column26.ColumnOrder = 20, ;
|
||||
Column26.ControlSource = "proc_tva", ;
|
||||
Column26.FontCharSet = 238, ;
|
||||
Column26.FontName = "Arial", ;
|
||||
@@ -7416,7 +7421,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column26.ReadOnly = .T., ;
|
||||
Column26.Width = 54, ;
|
||||
Column27.BackColor = 244,250,255, ;
|
||||
Column27.ColumnOrder = 17, ;
|
||||
Column27.ColumnOrder = 18, ;
|
||||
Column27.ControlSource = "perechec", ;
|
||||
Column27.FontCharSet = 238, ;
|
||||
Column27.FontName = "Arial", ;
|
||||
@@ -7425,7 +7430,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column27.ReadOnly = .F., ;
|
||||
Column27.Width = 104, ;
|
||||
Column28.BackColor = 244,250,255, ;
|
||||
Column28.ColumnOrder = 35, ;
|
||||
Column28.ColumnOrder = 36, ;
|
||||
Column28.ControlSource = "sectie", ;
|
||||
Column28.FontCharSet = 238, ;
|
||||
Column28.FontName = "Arial", ;
|
||||
@@ -7434,7 +7439,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column28.ReadOnly = .F., ;
|
||||
Column28.Width = 88, ;
|
||||
Column29.BackColor = 244,250,255, ;
|
||||
Column29.ColumnOrder = 29, ;
|
||||
Column29.ColumnOrder = 30, ;
|
||||
Column29.ControlSource = "nume_val", ;
|
||||
Column29.FontCharSet = 238, ;
|
||||
Column29.FontName = "Arial", ;
|
||||
@@ -7443,7 +7448,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column29.ReadOnly = .F., ;
|
||||
Column29.Width = 79, ;
|
||||
Column30.BackColor = 244,250,255, ;
|
||||
Column30.ColumnOrder = 39, ;
|
||||
Column30.ColumnOrder = 40, ;
|
||||
Column30.ControlSource = "id_partd", ;
|
||||
Column30.FontCharSet = 238, ;
|
||||
Column30.FontName = "Arial", ;
|
||||
@@ -7452,7 +7457,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column30.ReadOnly = .T., ;
|
||||
Column30.Width = 55, ;
|
||||
Column31.BackColor = 244,250,255, ;
|
||||
Column31.ColumnOrder = 40, ;
|
||||
Column31.ColumnOrder = 41, ;
|
||||
Column31.ControlSource = "id_partc", ;
|
||||
Column31.FontCharSet = 238, ;
|
||||
Column31.FontName = "Arial", ;
|
||||
@@ -7461,7 +7466,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column31.ReadOnly = .T., ;
|
||||
Column31.Width = 55, ;
|
||||
Column32.BackColor = 244,250,255, ;
|
||||
Column32.ColumnOrder = 34, ;
|
||||
Column32.ColumnOrder = 35, ;
|
||||
Column32.ControlSource = "gestout", ;
|
||||
Column32.FontCharSet = 238, ;
|
||||
Column32.FontName = "Arial", ;
|
||||
@@ -7470,7 +7475,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column32.ReadOnly = .F., ;
|
||||
Column32.Width = 92, ;
|
||||
Column33.BackColor = 244,250,255, ;
|
||||
Column33.ColumnOrder = 36, ;
|
||||
Column33.ColumnOrder = 37, ;
|
||||
Column33.ControlSource = "sucursala", ;
|
||||
Column33.FontCharSet = 238, ;
|
||||
Column33.FontName = "Arial", ;
|
||||
@@ -7479,7 +7484,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column33.ReadOnly = .F., ;
|
||||
Column33.Width = 121, ;
|
||||
Column34.BackColor = 244,250,255, ;
|
||||
Column34.ColumnOrder = 25, ;
|
||||
Column34.ColumnOrder = 26, ;
|
||||
Column34.ControlSource = "contract", ;
|
||||
Column34.FontCharSet = 238, ;
|
||||
Column34.FontName = "Arial", ;
|
||||
@@ -7488,7 +7493,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column34.ReadOnly = .T., ;
|
||||
Column34.Width = 65, ;
|
||||
Column35.BackColor = 244,250,255, ;
|
||||
Column35.ColumnOrder = 20, ;
|
||||
Column35.ColumnOrder = 21, ;
|
||||
Column35.ControlSource = "explicatie_tva", ;
|
||||
Column35.FontCharSet = 238, ;
|
||||
Column35.FontName = "Arial", ;
|
||||
@@ -7497,7 +7502,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column35.ReadOnly = .F., ;
|
||||
Column35.Width = 136, ;
|
||||
Column36.BackColor = 244,250,255, ;
|
||||
Column36.ColumnOrder = 18, ;
|
||||
Column36.ColumnOrder = 19, ;
|
||||
Column36.ControlSource = "cu_tva", ;
|
||||
Column36.FontCharSet = 238, ;
|
||||
Column36.FontName = "Arial", ;
|
||||
@@ -7517,7 +7522,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column37.ReadOnly = .F., ;
|
||||
Column37.Width = 58, ;
|
||||
Column38.BackColor = 244,250,255, ;
|
||||
Column38.ColumnOrder = 41, ;
|
||||
Column38.ColumnOrder = 42, ;
|
||||
Column38.ControlSource = "id_fact", ;
|
||||
Column38.FontCharSet = 238, ;
|
||||
Column38.FontName = "Arial", ;
|
||||
@@ -7526,7 +7531,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column38.ReadOnly = .T., ;
|
||||
Column38.Width = 94, ;
|
||||
Column39.BackColor = 244,250,255, ;
|
||||
Column39.ColumnOrder = 42, ;
|
||||
Column39.ColumnOrder = 43, ;
|
||||
Column39.ControlSource = "id_factd", ;
|
||||
Column39.FontCharSet = 238, ;
|
||||
Column39.FontName = "Arial", ;
|
||||
@@ -7535,7 +7540,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column39.ReadOnly = .T., ;
|
||||
Column39.Width = 75, ;
|
||||
Column40.BackColor = 244,250,255, ;
|
||||
Column40.ColumnOrder = 43, ;
|
||||
Column40.ColumnOrder = 44, ;
|
||||
Column40.ControlSource = "id_factc", ;
|
||||
Column40.FontCharSet = 238, ;
|
||||
Column40.FontName = "Arial", ;
|
||||
@@ -7555,7 +7560,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column41.Width = 22, ;
|
||||
Column42.BackColor = 244,250,255, ;
|
||||
Column42.Bound = .F., ;
|
||||
Column42.ColumnOrder = 21, ;
|
||||
Column42.ColumnOrder = 22, ;
|
||||
Column42.ControlSource = "Iif(Seek(tAct.taxcode,'saft_taxtable','taxcode'),saft_taxtable.taxname,'')", ;
|
||||
Column42.CurrentControl = "_combobox1", ;
|
||||
Column42.FontCharSet = 238, ;
|
||||
@@ -7566,7 +7571,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column42.Width = 184, ;
|
||||
Column43.BackColor = 244,250,255, ;
|
||||
Column43.Bound = .F., ;
|
||||
Column43.ColumnOrder = 22, ;
|
||||
Column43.ColumnOrder = 23, ;
|
||||
Column43.ControlSource = "Iif(Seek(tAct.paymentcode,'saft_mecanisme_plati','mcode'),saft_mecanisme_plati.paymentname,'')", ;
|
||||
Column43.CurrentControl = "_combobox1", ;
|
||||
Column43.FontCharSet = 238, ;
|
||||
@@ -7574,7 +7579,17 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
Column43.Name = "Column43", ;
|
||||
Column43.ReadOnly = .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" />
|
||||
|
||||
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
|
||||
*< 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 ;
|
||||
Alignment = 2, ;
|
||||
Caption = "Nr.Doc.", ;
|
||||
@@ -13613,6 +13651,9 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
This.grid1.Anchor = 11
|
||||
This.but_renunt1.Anchor = 8
|
||||
|
||||
If This.nid_set = 90101
|
||||
This.grid1.Column44.ReadOnly = .T.
|
||||
Endif
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE Load
|
||||
@@ -13683,6 +13724,19 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
|
||||
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.CalculeazaTotal()
|
||||
*!* 24.05.2011 ^
|
||||
@@ -13717,6 +13771,37 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
|
||||
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
|
||||
* Daca nu este activata SAFT 406 nu fac nimic
|
||||
IF !m.gl406
|
||||
@@ -14201,6 +14286,10 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
.Column35.ReadOnly = .T. && cod
|
||||
.Column25.ReadOnly = .T. && id_set
|
||||
ENDWITH
|
||||
*!* pastreaza blocarea NNIR pentru notele de inventar (id_set = 90101)
|
||||
IF Thisform.nid_set = 90101
|
||||
This.Column44.ReadOnly = .T.
|
||||
ENDIF
|
||||
*!* 10.08.2011 ^
|
||||
*!* pot selecta inregistrari din alte sucursale pentru operatiile de copiere, adaugare care
|
||||
This.cAles.ReadOnly = .F.
|
||||
@@ -14674,6 +14763,19 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
|
||||
thisform.cPaymentCode = ALLTRIM(tAct.paymentcode)
|
||||
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
|
||||
ADDPROPERTY(this, 'lInteractiveChange')
|
||||
LOCAL lnIdPart
|
||||
|
||||
@@ -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
|
||||
|
||||
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.
|
||||
@@ -22,6 +22,16 @@ cu `diag_spatiu.ps1`; **email doar la prag depasit**, tacere completa altfel. Su
|
||||
Sectiunile informative (recyclebin, UNDO, TEMP, istoric statistici/scheduler, top segmente, audit
|
||||
SYS, disc) se scriu doar cand exista deja o alerta — dau context, nu alerteaza singure.
|
||||
|
||||
`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`
|
||||
|
||||
@@ -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
|
||||
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:`.
|
||||
- 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`); simptom: crash la Createobject cu
|
||||
|
||||
53
docs/flux-modificare-stergere-nota-jurnal.md
Normal file
53
docs/flux-modificare-stergere-nota-jurnal.md
Normal 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.
|
||||
@@ -15,6 +15,10 @@ PL/SQL Developer.
|
||||
`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
|
||||
|
||||
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.
|
||||
@@ -60,6 +60,8 @@
|
||||
`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`;
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
Scripturile de migrare a schemei (si modelele pentru scripturi noi) sunt in
|
||||
`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.
|
||||
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):
|
||||
|
||||
@@ -16,6 +17,34 @@ Reguli confirmate de Marius (24.07.2026):
|
||||
- Aplicarea prin ODBC/`goExecutor`: sintaxa SQL*Plus `exec pachet.procedura(...)` nu functioneaza
|
||||
— foloseste `begin pachet.procedura(...); end;`.
|
||||
|
||||
## 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
|
||||
|
||||
@@ -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 |
|
||||
| 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` |
|
||||
|
||||
Documentatia **nu** se genereaza automat si nu exista niciun hook care s-o scrie — `livrare.ps1`
|
||||
|
||||
@@ -19,7 +19,9 @@ if (-not $TranscriptPath) {
|
||||
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 '[:\\/]','-')"
|
||||
if (Test-Path $dir) {
|
||||
$f = Get-ChildItem "$dir\*.jsonl" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# 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),
|
||||
# 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/
|
||||
# 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
|
||||
@@ -29,6 +30,12 @@ param(
|
||||
|
||||
$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)) {
|
||||
Write-Output ('EROARE: nu gasesc sqlplus la ' + $SqlPlus)
|
||||
exit 1
|
||||
@@ -173,16 +180,17 @@ select a.tablespace_name,
|
||||
round(a.max_bytes/1048576) mb_max,
|
||||
round(nvl(tf.free_bytes,0)/1048576) mb_liber,
|
||||
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
|
||||
then 'ATENTIE: MAXBYTES ATINS' end stare
|
||||
case when a.max_bytes > 0 and (nvl(tf.free_bytes,0) + a.creste_bytes) <
|
||||
greatest($PragTsMb * 1048576, a.max_bytes * $PragTsPct / 100)
|
||||
then 'ATENTIE: APROAPE FARA LOC' end stare
|
||||
from agg a, ts_free tf
|
||||
where a.tablespace_name = tf.tablespace_name(+)
|
||||
order by a.tablespace_name;
|
||||
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 @"
|
||||
set pagesize 0 linesize 100 trimspool on feedback off heading off
|
||||
with ts_free as (
|
||||
@@ -196,7 +204,8 @@ select 'TS_ATENTIE|' || a.tablespace_name
|
||||
from agg a, ts_free tf
|
||||
where a.tablespace_name = tf.tablespace_name(+)
|
||||
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
|
||||
"@
|
||||
$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
|
||||
}
|
||||
|
||||
# ---------- 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 ----------
|
||||
$r3 = Invoke-Sql -Sql @"
|
||||
set pagesize 0 linesize 250 trimspool on feedback off heading off
|
||||
@@ -369,12 +417,12 @@ exit
|
||||
$fraCritic = $false
|
||||
foreach ($line in ($r5c.Text -split "`r?`n")) {
|
||||
if ($line.Trim() -match '^FRAPCT\|([\d.]+)$') {
|
||||
if ([double]$Matches[1] -ge 80) { $fraCritic = $true }
|
||||
if ([double]$Matches[1] -ge $PragFraPct) { $fraCritic = $true }
|
||||
}
|
||||
}
|
||||
if ($fraCritic) {
|
||||
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 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 '===== 8. VERDICT ====='
|
||||
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 {
|
||||
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) {
|
||||
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).'
|
||||
if (-not $ConnStrSys) {
|
||||
|
||||
689
utile/publicare_scripturi.ps1
Normal file
689
utile/publicare_scripturi.ps1
Normal 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
|
||||
Reference in New Issue
Block a user