diff --git a/Ferestre/frm_import_extrase_banca.sc2 b/Ferestre/frm_import_extrase_banca.sc2 index bb2375b..bb34bcf 100644 --- a/Ferestre/frm_import_extrase_banca.sc2 +++ b/Ferestre/frm_import_extrase_banca.sc2 @@ -57,6 +57,12 @@ DEFINE CLASS form1 AS form *< OBJECTDATA: ObjPath="grdConturi.cDenumire.Text1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="grdConturi.cDataOra.Header1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="grdConturi.cDataOra.Text1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdConturi.cSoldI.Header1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdConturi.cSoldI.Text1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdConturi.cSoldF.Header1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdConturi.cSoldF.Text1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdConturi.cSoldDif.Header1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdConturi.cSoldDif.Text1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="But_sterge1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="grdConfigurareConturi" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="grdConfigurareConturi.cCodFiscal.Header1" UniqueID="" Timestamp="" /> @@ -133,6 +139,7 @@ DEFINE CLASS form1 AS form * *m: cauta_fdoc *m: completeazaclientiroa + *m: completeazasolduri *m: connectroa *m: creeazanote *m: disconnectroa @@ -507,7 +514,7 @@ DEFINE CLASS form1 AS form ADD OBJECT 'grdConturi' AS grid WITH ; Anchor = 11, ; - ColumnCount = 12, ; + ColumnCount = 15, ; DeleteMark = .F., ; HeaderHeight = 30, ; Height = 226, ; @@ -586,7 +593,19 @@ DEFINE CLASS form1 AS form Column12.ControlSource = "dataora", ; Column12.Name = "cDataOra", ; Column12.ReadOnly = .T., ; - Column12.Width = 108 + Column12.Width = 108, ; + Column13.ControlSource = "sold_i", ; + Column13.Name = "cSoldI", ; + Column13.ReadOnly = .T., ; + Column13.Width = 75, ; + Column14.ControlSource = "sold_f", ; + Column14.Name = "cSoldF", ; + Column14.ReadOnly = .T., ; + Column14.Width = 75, ; + Column15.ControlSource = "sold_dif", ; + Column15.Name = "cSoldDif", ; + Column15.ReadOnly = .T., ; + Column15.Width = 75 *< END OBJECT: BaseClass="grid" /> ADD OBJECT 'grdConturi.cAcont.Header1' AS header WITH ; @@ -785,6 +804,51 @@ DEFINE CLASS form1 AS form Name = "Text1" *< END OBJECT: BaseClass="textbox" /> + ADD OBJECT 'grdConturi.cSoldDif.Header1' AS header WITH ; + Alignment = 2, ; + Caption = "Diferenta", ; + Name = "Header1" + *< END OBJECT: BaseClass="header" /> + + ADD OBJECT 'grdConturi.cSoldDif.Text1' AS textbox WITH ; + BackColor = 255,255,255, ; + BorderStyle = 0, ; + ForeColor = 0,0,0, ; + Margin = 0, ; + Name = "Text1", ; + ReadOnly = .T. + *< END OBJECT: BaseClass="textbox" /> + + ADD OBJECT 'grdConturi.cSoldF.Header1' AS header WITH ; + Alignment = 2, ; + Caption = "Sold final", ; + Name = "Header1" + *< END OBJECT: BaseClass="header" /> + + ADD OBJECT 'grdConturi.cSoldF.Text1' AS textbox WITH ; + BackColor = 255,255,255, ; + BorderStyle = 0, ; + ForeColor = 0,0,0, ; + Margin = 0, ; + Name = "Text1", ; + ReadOnly = .T. + *< END OBJECT: BaseClass="textbox" /> + + ADD OBJECT 'grdConturi.cSoldI.Header1' AS header WITH ; + Alignment = 2, ; + Caption = "Sold initial", ; + Name = "Header1" + *< END OBJECT: BaseClass="header" /> + + ADD OBJECT 'grdConturi.cSoldI.Text1' AS textbox WITH ; + BackColor = 255,255,255, ; + BorderStyle = 0, ; + ForeColor = 0,0,0, ; + Margin = 0, ; + Name = "Text1", ; + ReadOnly = .T. + *< END OBJECT: BaseClass="textbox" /> + ADD OBJECT 'grdConturi.cTip.Header1' AS header WITH ; Alignment = 2, ; Caption = "Tip", ; @@ -1359,6 +1423,17 @@ DEFINE CLASS form1 AS form PROCEDURE completeazaclientiroa ENDPROC + PROCEDURE completeazasolduri + LPARAMETERS toImport + LOCAL lnIncasari, lnPlati + lnIncasari = 0 + lnPlati = 0 + CALCULATE SUM(suma) FOR tip = 'C' TO lnIncasari IN C_IMPORT_TEMP + CALCULATE SUM(suma) FOR tip = 'D' TO lnPlati IN C_IMPORT_TEMP + REPLACE valuta WITH m.toImport.cValuta, sold_i WITH m.toImport.nSoldInitial, sold_f WITH m.toImport.nSoldFinal IN cConturi + REPLACE sold_dif WITH cConturi.sold_i + m.lnIncasari - m.lnPlati - cConturi.sold_f IN cConturi + ENDPROC + PROCEDURE connectroa ENDPROC @@ -1427,6 +1502,7 @@ DEFINE CLASS form1 AS form * Colorez cu albastru inregistrarile pentru import this.grdConturi.SetAll("DynamicForeColor", "IIF(cConturi.note = 1, RGB(0,128,0), IIF(cConturi.import = 1, RGB(0,0,128), RGB(0,0,0)))","Column") + this.grdConturi.cSoldDif.DynamicForeColor = "IIF(NVL(sold_dif,0)<>0, RGB(255,0,0), RGB(0,0,0))" this.gridextra1.setup() this.gridextra2.setup() @@ -1438,7 +1514,7 @@ DEFINE CLASS form1 AS form PROCEDURE Load CREATE CURSOR cConturi (ales N(1), note N(1), import N(1), banca C(100), iban C(100), clasa C(100), fisier C(250), ; - tip C(20), extensie C(4), tipclasa C(100), cont C(4), acont C(4), part_nou L, factura L, comanda L, denumire C(100), id_part N(10), dataora T) + tip C(20), extensie C(4), tipclasa C(100), cont C(4), acont C(4), part_nou L, factura L, comanda L, denumire C(100), id_part N(10), dataora T, valuta C(3), sold_i N(15,2) NULL, sold_f N(15,2) NULL, sold_dif N(15,2) NULL, sold_dubl N(15,2)) * Trebuie sa citesc configurarile pentru fiecare IBAN CREATE CURSOR cConfigConturi(iban C(100), id_part N(10), denumire C(200), cod_fiscal C(50), cont C(4), acont C(4)) @@ -1477,7 +1553,7 @@ DEFINE CLASS form1 AS form Select cConturi Append From Dbf('cConturiTemp') Use In (Select('cConturiTemp')) - UPDATE cConturi SET import = 0, ales = 0, note = 0 + UPDATE cConturi SET import = 0, ales = 0, note = 0, sold_i = .NULL., sold_f = .NULL., sold_dif = .NULL., sold_dubl = 0 * Completez numele partenerilor tip BANCA * Caut si pentru conturile care au denumirea partenerului completata, in cazul in care s-a modificat intre timp @@ -1598,13 +1674,78 @@ DEFINE CLASS form1 AS form If m.llSucces AND !m.tlIncarcaBackup Select actactan_temp IF USED('actactan') + * actactan_temp are structura vact (SELECT * FROM vact WHERE 1=2), un camp nou pe actactan nu supravietuieste acestui Append From Dbf - salvez randurile marcate intr-un cursor paralel, cheie pe pozitia in randurile nesterse (Recno() nu coincide cu pozitia din tact dupa un DELETE fara PACK) + IF Type('actactan.listoric') = 'L' OR Type('actactan.dublura') = 'L' OR Type('actactan.ngrupa') = 'N' + lnSeqMarcaj = 0 + IF Type('actactan.listoric') = 'L' + Create Cursor cIstoricMarcaj (nrseq N(6)) + Index On nrseq Tag nrseq + ENDIF + IF Type('actactan.dublura') = 'L' + Create Cursor cDubluraMarcaj (nrseq N(6)) + Index On nrseq Tag nrseq + ENDIF + IF Type('actactan.ngrupa') = 'N' + Create Cursor cGrupaMarcaj (nrseq N(6), ngrupa I, npoz I, csursa C(1)) + Index On nrseq Tag nrseq + ENDIF + Select actactan + Scan + lnSeqMarcaj = lnSeqMarcaj + 1 + IF Type('actactan.listoric') = 'L' AND listoric + Insert Into cIstoricMarcaj (nrseq) Values (lnSeqMarcaj) + ENDIF + IF Type('actactan.dublura') = 'L' AND dublura + Insert Into cDubluraMarcaj (nrseq) Values (lnSeqMarcaj) + ENDIF + IF Type('actactan.ngrupa') = 'N' AND ngrupa > 0 + Insert Into cGrupaMarcaj (nrseq, ngrupa, npoz, csursa) Values (lnSeqMarcaj, actactan.ngrupa, actactan.npoz, actactan.csursa_f) + ENDIF + Endscan + ENDIF + Select actactan_temp Append From Dbf('actactan') - ENDIF + ENDIF - Select .F. As ales, a.explicatia4 As iban, Iif(!Empty(Nvl(a.id_jtva_coloana, 0)), 1, 0) As Cu_tva, Cast(0 As N(2)) As tipnota, a.*, b.denumire As explicatie_tva_2 ; + Select .F. As ales, a.explicatia4 As iban, Iif(!Empty(Nvl(a.id_jtva_coloana, 0)), 1, 0) As Cu_tva, Cast(0 As N(2)) As tipnota, .F. As listoric, .F. As dublura, Cast(0 As I) As ngrupa, Cast(0 As I) As npoz, Space(1) As csursa_f, a.*, b.denumire As explicatie_tva_2 ; From actactan_temp a Left Join crsExplicatiiTVATemp b On a.id_jtva_coloana = b.id_jtva_coloana ; Into Cursor tact Readwrite + IF Used('cIstoricMarcaj') + Select tact + Scan + If Seek(Recno(), 'cIstoricMarcaj', 'nrseq') + Replace listoric With .T. + Endif + Endscan + Use In cIstoricMarcaj + ENDIF + IF Used('cDubluraMarcaj') + Select tact + Scan + If Seek(Recno(), 'cDubluraMarcaj', 'nrseq') + Replace dublura With .T. + Endif + Endscan + Use In cDubluraMarcaj + ENDIF + IF Used('cGrupaMarcaj') + * renumerotare in ordinea din tact: grupele consecutive devin 1,2,3... + lnGrupaNoua = 0 + lnGrupaVeche = 0 + Select tact + Scan + If Seek(Recno(), 'cGrupaMarcaj', 'nrseq') + If cGrupaMarcaj.ngrupa <> lnGrupaVeche + lnGrupaVeche = cGrupaMarcaj.ngrupa + lnGrupaNoua = lnGrupaNoua + 1 + Endif + Replace ngrupa With lnGrupaNoua, npoz With cGrupaMarcaj.npoz, csursa_f With cGrupaMarcaj.csursa + Endif + Endscan + Use In cGrupaMarcaj + ENDIF + Update tact Set explicatie_tva = explicatie_tva_2, explicatia4 = '', id_Set = m.lnIdSet, explicatia5 = 'IMPORT ' + STRTRAN(TTOC(DATETIME(),3), 'T', ' ') UPDATE tAct SET nract = INT(VAL(DTOS(dataact) + ALLTRIM(STR(RECNO())))) WHERE EMPTY(NVL(nract,0)) @@ -1649,8 +1790,10 @@ DEFINE CLASS form1 AS form Go Top llNotaNoua = .T. llMaximize = .T. - loForm = Createobject([frm_modific2024], m.lnIdSet, m.llNotaNoua) + loForm = Createobject([frm_modific2024], m.lnIdSet, m.llNotaNoua, m.loBackupXML) loForm.lb_titlu_alb_b121.Caption = 'Import extrase bancare, deconturi curieri, procesatori plati' + *!* activeaza totalurile si autosalvarea automate, specifice acestui apelant + loForm.lActivExtrase = .T. Select tact loForm.Show(1, m.llMaximize) @@ -2096,7 +2239,6 @@ DEFINE CLASS form1 AS form amessagebox("Nu au fost gasite importuri in luna curenta") RETURN Endif - SET STEP ON lcMenu = '' SELECT crsStergeri SCAN @@ -2137,33 +2279,127 @@ DEFINE CLASS form1 AS form ENDPROC PROCEDURE verificaimport - * Verifica daca mai exista inregistrari 90023 in luna curenta - Local llExista, lcSelect, lcSql, llSucces - Private pnReturnValue, pnSuma, pdDataAct, pcScd, pcScc - pnReturnValue = 0 + * Numara cate randuri din import (actactan) sunt deja contate dintr-un import anterior 90023, in luna curenta + Local lcSelect, lcSql, lcRaw, llSucces, lnDuplicate + Local ldDataAct, lnSuma, lcScd, lcScc, lcExplicatie, llGasit + Local lnGrupa, lnGrupaDublura, lnNouDublura + Local llBancaPeD, lnIdPartCurent lcSelect = SELECT() + lnDuplicate = 0 - lcSql = [select COUNT(*) as nr from act where an=?gnAn and luna = ?gnLuna and id_set=90023 and sters=0 and suma = ?pnSuma and dataact = ?pdDataAct and scd = ?pcScd and scc = ?pcScc] + lcRaw = 'cActVerifRaw' + IF USED(m.lcRaw) + USE IN (m.lcRaw) + ENDIF + lcSql = [select dataact, suma, scd, scc, explicatia, id_partd, id_partc from act where an=?gnAn and luna=?gnLuna and id_set=90023 and sters=0] + llSucces = goExecutor.oExecuta(m.lcSql, m.lcRaw) + IF !m.llSucces + SELECT (m.lcSelect) + RETURN 0 + ENDIF + + * .F. AS folosit: marcheaza randurile ACT deja perechate, ca un rand ACT sa nu acopere doua randuri de import + SELECT *, .F. AS folosit FROM (m.lcRaw) INTO CURSOR cActVerif READWRITE + USE IN (m.lcRaw) + + IF TYPE('actactan.dublura') = 'U' + * ALTER TABLE da eroarea 1115 pe cursor cu nume de camp peste 10 caractere (explicatia4, id_sucursala) + SELECT *, .F. AS dublura FROM actactan INTO CURSOR cActDublura READWRITE + USE IN actactan + SELECT * FROM cActDublura INTO CURSOR actactan READWRITE + USE IN cActDublura + ENDIF SELECT actactan + REPLACE ALL dublura WITH .F. SCAN - pnSuma = suma - pdDataAct = dataact - pcScd = ALLTRIM(scd) - pcScc = ALLTRIM(scc) - llSucces = goExecutor.oSelecteaza2Value(m.lcSql, @pnReturnValue) - If !m.llSucces - IF m.pnReturnValue > 0 - EXIT - ENDIF - ELSE - EXIT - Endif + ldDataAct = dataact + lnSuma = suma + lcScd = ALLTRIM(scd) + lcScc = ALLTRIM(scc) + lcExplicatie = ALLTRIM(explicatia) + llBancaPeD = (LEFT(m.lcScd,3)='512') + lnIdPartCurent = NVL(IIF(m.llBancaPeD, id_partc, id_partd),0) + + SELECT cActVerif + * doar contul de banca: contul corespondent poate fi corectat la contare + LOCATE FOR !folosit AND dataact = m.ldDataAct AND suma = m.lnSuma AND IIF(m.llBancaPeD, ALLTRIM(scd) == m.lcScd, ALLTRIM(scc) == m.lcScc) AND ALLTRIM(explicatia) == m.lcExplicatie + IF !FOUND() + * fara potrivire pe explicatie: regula veche, pentru note vechi sau explicatie modificata dupa import + LOCATE FOR !folosit AND dataact = m.ldDataAct AND suma = m.lnSuma AND IIF(m.llBancaPeD, ALLTRIM(scd) == m.lcScd, ALLTRIM(scc) == m.lcScc) + ENDIF + llGasit = FOUND() + IF m.llGasit + REPLACE folosit WITH .T. + ENDIF + IF !m.llGasit AND m.lnIdPartCurent > 0 + * ponytail: submultimea = toate randurile nefolosite din zi+cont+partener, fara cautare de combinatii - extinde cu subseturi daca apar cazuri ratate + IF m.llBancaPeD + SELECT SUM(suma) AS sumagrup, COUNT(*) AS nr FROM cActVerif WHERE !folosit AND dataact = m.ldDataAct AND ALLTRIM(scd) == m.lcScd AND NVL(id_partc,0) = m.lnIdPartCurent INTO CURSOR cSumaGrupVerif + ELSE + SELECT SUM(suma) AS sumagrup, COUNT(*) AS nr FROM cActVerif WHERE !folosit AND dataact = m.ldDataAct AND ALLTRIM(scc) == m.lcScc AND NVL(id_partd,0) = m.lnIdPartCurent INTO CURSOR cSumaGrupVerif + ENDIF + IF cSumaGrupVerif.nr >= 2 AND ROUND(NVL(cSumaGrupVerif.sumagrup,0),2) == ROUND(m.lnSuma,2) + llGasit = .T. + SELECT cActVerif + IF m.llBancaPeD + REPLACE ALL folosit WITH .T. FOR !folosit AND dataact = m.ldDataAct AND ALLTRIM(scd) == m.lcScd AND NVL(id_partc,0) = m.lnIdPartCurent + ELSE + REPLACE ALL folosit WITH .T. FOR !folosit AND dataact = m.ldDataAct AND ALLTRIM(scc) == m.lcScc AND NVL(id_partd,0) = m.lnIdPartCurent + ENDIF + ENDIF + USE IN cSumaGrupVerif + ENDIF + + SELECT actactan + REPLACE dublura WITH m.llGasit + IF m.llGasit + lnDuplicate = m.lnDuplicate + 1 + ENDIF ENDSCAN && actactan - llExista = (m.pnReturnValue > 0) + IF Type('actactan.ngrupa') = 'N' + * randul impartit pe facturi (ngrupa>0) se marcheaza/sterge intreg, niciodata jumatate + SELECT DISTINCT ngrupa FROM actactan WHERE ngrupa > 0 INTO CURSOR cGrupeVerif + SELECT cGrupeVerif + SCAN + lnGrupa = ngrupa + SELECT actactan + COUNT FOR ngrupa = m.lnGrupa AND dublura TO lnGrupaDublura + llGasit = (m.lnGrupaDublura > 0) + IF !m.llGasit + * fara potrivire pe rand in grupa: caut suma intreaga a grupei ca un singur rand ACT vechi, neimpartit + SUM suma FOR ngrupa = m.lnGrupa TO lnSuma + LOCATE FOR ngrupa = m.lnGrupa + ldDataAct = dataact + lcScd = ALLTRIM(scd) + lcScc = ALLTRIM(scc) + llBancaPeD = (LEFT(m.lcScd,3)='512') + lcExplicatie = ALLTRIM(explicatia) - Select (m.lcSelect) - Return m.llExista + SELECT cActVerif + LOCATE FOR !folosit AND dataact = m.ldDataAct AND suma = m.lnSuma AND IIF(m.llBancaPeD, ALLTRIM(scd) == m.lcScd, ALLTRIM(scc) == m.lcScc) AND ALLTRIM(explicatia) == m.lcExplicatie + IF !FOUND() + LOCATE FOR !folosit AND dataact = m.ldDataAct AND suma = m.lnSuma AND IIF(m.llBancaPeD, ALLTRIM(scd) == m.lcScd, ALLTRIM(scc) == m.lcScc) + ENDIF + llGasit = FOUND() + IF m.llGasit + REPLACE folosit WITH .T. + ENDIF + ENDIF + IF m.llGasit + SELECT actactan + COUNT FOR ngrupa = m.lnGrupa AND !dublura TO lnNouDublura + lnDuplicate = m.lnDuplicate + m.lnNouDublura + REPLACE ALL dublura WITH .T. FOR ngrupa = m.lnGrupa + ENDIF + SELECT cGrupeVerif + ENDSCAN && cGrupeVerif + USE IN (SELECT('cGrupeVerif')) + ENDIF + + USE IN (SELECT('cActVerif')) + SELECT (m.lcSelect) + Return m.lnDuplicate ENDPROC @@ -2289,10 +2525,11 @@ DEFINE CLASS form1 AS form PROCEDURE cmdGenereazaNote.Click Local llSucces, lnSucces, lnButon, llContafin, lnIdSet - Local lcCodAMEF, llExistaNote + Local lcCodAMEF, lnDuplicate, lnTotalImport Local lcAcont, lcCont, lcIBAN, lnIdPart Local llPartNou - Local lcExplicatie, lcPart, ldData, llComanda, llFactura + Local lcExplicatie, lcPart, ldData, llComanda, llFactura, lcGardaSursa + Local lcAvertizari, llValutaCont Local loImport As "ImportNote" @@ -2302,6 +2539,7 @@ DEFINE CLASS form1 AS form lcSelect = SELECT() llSucces = .T. lnIdSet = 90023 + lcAvertizari = '' ldData1 = Thisform.txtData1.Value ldData2 = Thisform.txtData2.Value ldData = thisform.txtData.Value @@ -2321,7 +2559,7 @@ DEFINE CLASS form1 AS form LOCATE FOR ales = 1 AND Import = 1 AND note = 0 llSucces = FOUND() IF !m.llSucces - AMESSAGEBOX('Alegeti un cont/decont incarcat pentru care nu s-au generat note!',0+48,_scren.caption) + AMESSAGEBOX('Alegeti un cont/decont incarcat pentru care nu s-au generat note!',0+48,_Screen.Caption) ENDIF ENDIF @@ -2359,6 +2597,12 @@ DEFINE CLASS form1 AS form If !m.llSucces Exit Endif + If !Empty(loImport.oImport.cAvertizareCurs) + lcAvertizari = lcAvertizari + Iif(!Empty(m.lcAvertizari), Chr(13), '') + loImport.oImport.cAvertizareCurs + Endif + + * contul facturii (impartit pe cAlocTemp) nu e suprascris de configurarea pe explicatie/partener + lcGardaSursa = IIF(Type('cActTemp.csursa_f') = 'C', ' AND Empty(csursa_f)', '') * Completez cont, acont, parteneri pe explicatiile din din cConfigExplicatii Select explicatie, id_part, denumire, Cont, acont From cConfigExplicatii Where iban = m.lcIBAN And !Empty(Nvl(explicatie, '')) Into Cursor cContTemp @@ -2375,9 +2619,9 @@ DEFINE CLASS form1 AS form Update cActTemp Set id_partc = m.lnIdPart, partc = m.lcPart Where m.lcExplicatie$UPPER(ALLTRIM(explicatia)) AND scd = m.lcContBanca AND EMPTY(NVL(id_partc, 0)) ENDIF IF !EMPTY(m.lcCont) - Update cActTemp Set scd = m.lcCont, ascd = m.lcAcont Where m.lcExplicatie$UPPER(ALLTRIM(explicatia)) AND scc = m.lcContBanca - Update cActTemp Set scc = m.lcCont, ascc = m.lcAcont Where m.lcExplicatie$UPPER(ALLTRIM(explicatia)) AND scd = m.lcContBanca - ENDIF + Update cActTemp Set scd = m.lcCont, ascd = m.lcAcont Where m.lcExplicatie$UPPER(ALLTRIM(explicatia)) AND scc = m.lcContBanca &lcGardaSursa + Update cActTemp Set scc = m.lcCont, ascc = m.lcAcont Where m.lcExplicatie$UPPER(ALLTRIM(explicatia)) AND scd = m.lcContBanca &lcGardaSursa + ENDIF Endscan Use In (Select('cContTemp')) @@ -2388,37 +2632,63 @@ DEFINE CLASS form1 AS form lcCont = Cont lcAcont = acont lnIdPart = id_part - Update cActTemp Set scd = m.lcCont, ascd = m.lcAcont Where id_partd = m.lnIdPart - Update cActTemp Set scc = m.lcCont, ascc = m.lcAcont Where id_partc = m.lnIdPart + Update cActTemp Set scd = m.lcCont, ascd = m.lcAcont Where id_partd = m.lnIdPart &lcGardaSursa + Update cActTemp Set scc = m.lcCont, ascc = m.lcAcont Where id_partc = m.lnIdPart &lcGardaSursa Endscan Use In (Select('cContTemp')) If !Used('actactan') Select * From cActTemp Into Cursor actactan Readwrite Else + IF Type('cActTemp.ngrupa') = 'N' + * ngrupa unic intre conturi/fisiere acumulate in acelasi actactan + Update cActTemp Set ngrupa = ngrupa + Reccount('actactan') Where ngrupa > 0 + ENDIF Select actactan Append From Dbf('cActTemp') Endif Use In (Select('cActTemp')) Release loImport Endscan + If !Empty(m.lcAvertizari) + AMESSAGEBOX(m.lcAvertizari, 0+48, _Screen.Caption) + Endif Endif && llSucces llSucces = llSucces and USED('actactan') * verific daca mai exista import 90023 IF m.llSucces - llExistaNote = Thisform.VerificaImport() - If m.llExistaNote - If AMESSAGEBOX('Atentie! Exista deja note contabile generate dintr-un import anterior [tip operatie 90023]!' + Chr(13) + ; - 'Doriti sa continuati?', 4 + 32, _Screen.Caption) <> 6 - llSucces = .F. + UPDATE cConturi SET sold_dubl = 0 WHERE ales = 1 AND import = 1 AND note = 0 + lnTotalImport = RECCOUNT('actactan') + lnDuplicate = Thisform.VerificaImport() + If m.lnDuplicate > 0 + If AMESSAGEBOX('Din ' + TRANSFORM(m.lnTotalImport) + ' randuri, ' + TRANSFORM(m.lnDuplicate) + ' sunt deja contate dintr-un import anterior (tip operatie 90023). Le scoateti din import?', 4 + 32, _Screen.Caption) = 6 + SELECT actactan + * PACK esueaza pe cursor (nu suporta 'Invalid operation') - DELETE ramane suficient cat timp SET DELETED ON + SET DELETED ON + SELECT cConturi + SCAN FOR ales = 1 AND import = 1 AND note = 0 + lcIBAN = Alltrim(Nvl(iban,'')) + llValutaCont = (Alltrim(Nvl(valuta,'RON')) <> 'RON') + SELECT Sum(Iif(Left(Nvl(scd,''),3)='512', Iif(m.llValutaCont, suma_val, suma), 0.00)) - Sum(Iif(Left(Nvl(scc,''),3)='512', Iif(m.llValutaCont, suma_val, suma), 0.00)) As dif From actactan Where dublura And Alltrim(Nvl(explicatia4,'')) == m.lcIBAN Into Cursor cDublTemp + REPLACE sold_dubl WITH Nvl(cDublTemp.dif,0) IN cConturi + USE IN cDublTemp + ENDSCAN + SELECT actactan + DELETE FOR dublura + IF m.lnTotalImport - m.lnDuplicate = 0 + AMESSAGEBOX('Nu a ramas nicio inregistrare de importat!', 0 + 48, _Screen.Caption) + llSucces = .F. + ENDIF Endif ENDIF ENDIF If m.llSucces + SELECT iban, valuta, sold_i, sold_f, sold_dubl From cConturi Where ales = 1 And import = 1 And note = 0 Into Cursor cSolduriExtrase llSucces = Thisform.ModificaNote() + USE IN cSolduriExtrase Endif If m.llSucces @@ -2443,7 +2713,7 @@ DEFINE CLASS form1 AS form Local llSucces, lnOptiune, ldData1, ldData2, ldData Local lcAcontBanca, lcIBAN, lcValuta lcIBAN = '' - lnOptiune = xmenu('\ 0 && filtrul a taiat randuri, soldul din fisier nu mai e de incredere + This.oImport.nSoldInitial = .Null. + This.oImport.nSoldFinal = .Null. + Endif ELSE * import tot fisierul daca este completata ldData pentru deconturile de la curieri UPDATE C_IMPORT_TEMP SET data = m.ldData @@ -222,6 +231,34 @@ Define Class ImportNote As Custom Endproc Enddefine && ImportNote +* Clasa directa pentru importul general (aceeasi ca optiunea din meniu); '' = ramane pe ExtrasBanca_General +Function DetecteazaClasaExtrasGeneral + Lparameters tcFile, tcFileExt + Local lcClasa, lcExt, lnFisier, lcRand + lcClasa = '' + lcExt = Upper(Alltrim(m.tcFileExt)) + Do Case + Case m.lcExt == 'TXT' && MT940 Raiffeisen: taguri ^NN in :86:, spre deosebire de BCR/Unicredit + If '^20' $ Filetostr(m.tcFile) + lcClasa = 'ExtrasBanca_RAIFFEISEN_TXT_MT940' + Endif + Case m.lcExt == 'XML' && CreditEurope: radacina + If '' $ Lower(Filetostr(m.tcFile)) + lcClasa = 'ExtrasBanca_CREDITEUROPE_XML' + Endif + Case m.lcExt == 'CSV' && Unicredit: antetul verificat in ExtrasBanca_UNICREDIT_CSV.Parse + lnFisier = Fopen(m.tcFile) + If m.lnFisier <> -1 + lcRand = Fgets(m.lnFisier) + Fclose(m.lnFisier) + If [Titlu cont;Cont;Valuta;Sold deschidere;Sold inchidere] $ m.lcRand + lcClasa = 'ExtrasBanca_UNICREDIT_CSV' + Endif + Endif + Endcase + Return m.lcClasa +Endfunc && DetecteazaClasaExtrasGeneral + ************************************* * Clasa factory pentru import extras banca @@ -247,6 +284,9 @@ Define Class ExtrasBanca As Custom cIBAN = '' && cont bancar IBAN la care se refere extrasul cValuta = 'RON' + nSoldInitial = .Null. && sold din fisier, .NULL. daca formatul nu il are sau filtrul pe perioada l-a invalidat + nSoldFinal = .Null. + cAvertizareCurs = '' && avertizari CursLaData, o linie per data cBIC = '' && cod BIC banca / nu se mai foloseste ??? nNr = 0 && statement number/ numar extras @@ -282,7 +322,7 @@ Define Class ExtrasBanca As Custom lcContBanca = m.loHash.GetValue('cContBanca') lcAcontBanca = m.loHash.GetValue('cAContBanca') lcContIBAN = loHash.GetValue('cContIban') - lnIdPartenerBanca = loHash.GetValue('nIdPartBanca') + lnIdPartenerBanca = loHash.GetValue('nIdPartenerBanca') lcBanca = m.loHash.GetValue('cBanca') llCreeazaParteneri = loHash.GetValue('lCreeazaParteneri') && creeaza parteneri daca nu exista codul fiscal in baza de date @@ -321,8 +361,10 @@ Define Class ExtrasBanca As Custom Local lcComanda, lcDenumire2, lcPartenerCasa, lcTip2, lnVariante, llExcludeOriginal Local lnDenumire, lnDocument, lnIdPartenerCasa, lnVariante, loPartener Local lcGrupIdLista, lcSqlGrup, lnIdPartAlternativ, lcPartAlternativ + Local lcSqlIstoric, llIstoricOk, lcCheieTxt + Local lcSqlSolduri, llSolduriOk, llAlocatFacturi - PRIVATE pcContBanca, pnIdPartBanca + PRIVATE pcContBanca, pnIdPartBanca, pcContBancaTert, pnIdPartenerTert lcSelect = Select() @@ -430,20 +472,70 @@ Define Class ExtrasBanca As Custom Select cActTemp Append From Dbf('C_IMPORT_TEMP') + * Cheie invatata din istoric (ACT ID_SET=90023, ultimele 12 luni, linii cu partener pe 401/4111): + * text normalizat din explicatia salvata -> id_part, doar cand cheia a dus mereu la acelasi partener + lcSqlIstoric = [select (case when a.scd in ('401','4111') then a.id_partd else a.id_partc end) as id_part, a.explicatia ] + ; + [from act a join nom_parteneri p on p.id_part = (case when a.scd in ('401','4111') then a.id_partd else a.id_partc end) ] + ; + [where a.id_set = 90023 and a.sters = 0 and (a.scd in ('401','4111') or a.scc in ('401','4111')) ] + ; + [and (a.an*12+a.luna) >= (?gnAn*12+?gnLuna-12) and p.sters = 0 and p.inactiv = 0] + llIstoricOk = goExecutor.oExecuta(m.lcSqlIstoric, "cIstoricBrut") + If m.llIstoricOk + Create Cursor cCheiIstoric (cheie C(63), id_part N(9)) + Select cIstoricBrut + Scan + lcCheieTxt = TextIstoricNormalizat(explicatia) + If !Empty(m.lcCheieTxt) + Insert Into cCheiIstoric (cheie, id_part) Values (m.lcCheieTxt, cIstoricBrut.id_part) + Endif + Endscan + Use In (Select("cIstoricBrut")) + Select cheie, Min(id_part) As id_part From cCheiIstoric Group By cheie ; + Having Count(Distinct id_part) = 1 And Count(*) >= 2 Into Cursor cCheieInvatata Readwrite + Use In (Select("cCheiIstoric")) + Index On cheie Tag cheie + Endif + + * Solduri facturi deschise (401/4111 + extinderile 404/461/462; 419/4091-4094 doar pentru avans existent) + If This.lFactura + lcSqlSolduri = [select i.id_part, i.cont, i.acont, i.id_fact, max(i.nract) nract, min(i.dataact) dataact, ] + ; + [max(i.id_valuta) id_valuta, sum(i.precdeb+i.debit-i.preccred-i.credit) sold ] + ; + [from ireg_parteneri i where i.an = ?gnAn and i.luna = ?gnLuna ] + ; + [and i.cont in ('401','4111','419','4091','4092','4093','4094','404','461','462') ] + ; + [group by i.id_part, i.cont, i.acont, i.id_fact ] + ; + [having sum(i.precdeb+i.debit-i.preccred-i.credit) <> 0] + llSolduriOk = goExecutor.oExecuta(m.lcSqlSolduri, "cSolduriBrut") + If m.llSolduriOk + * candidati de alocat: 4111/461 sold debitor (incasari), 401/404/462 sold creditor (plati), doar valuta nationala + Select id_part, Cont, acont, id_fact, nract, dataact, id_valuta, ; + Cast(Abs(sold) As N(15, 2)) As ramas ; + From cSolduriBrut ; + Where ((Inlist(Alltrim(Cont), '4111', '461') And sold > 0) Or (Inlist(Alltrim(Cont), '401', '404', '462') And sold < 0)) ; + And Inlist(Nvl(id_valuta, 0), 0, 3) ; + Into Cursor cSolduriFact Readwrite + Index On id_part Tag id_part + * parteneri cu avans (419 sau 4091-4094) deja deschis: mai jos doar N/S, fara FIFO/avans pe rest + Select Distinct id_part From cSolduriBrut Where Inlist(Alltrim(Cont), '419', '4091', '4092', '4093', '4094') Into Cursor cAvansExistent Readwrite + Index On id_part Tag id_part + Use In (Select("cSolduriBrut")) + Endif + Create Cursor cAlocTemp (nrec I, npoz I, id_fact I, nract I, cont C(4), acont C(20), suma N(15, 2), csursa C(1)) + Endif + * Caut/creez parteneri Create Cursor cGrupParteneriCui (id_part_ales N(9), id_part N(9), denumire C(100)) + Create Cursor cIbanDeSalvat (id_part N(9), iban C(24), denumire C(100)) SELECT distinct cod_fiscal, denumire, iban FROM cActTemp INTO CURSOR cParteneriTemp READWRITE SELECT cParteneriTemp lcRecc = Transform(Reccount()) SCAN lcCodFiscal = Upper(Alltrim(cod_fiscal)) lcDenumire = Upper(Alltrim(denumire)) - lcIBan = UPPER(ALLTRIM(NVL(iban,''))) + lcIBanPart = UPPER(ALLTRIM(NVL(iban,''))) lcRecno = Transform(Recno()) lnIdPartener = 0 Wait Window 'Cautare parteneri ' + Transform(Recno()) + '/' + m.lcRecc Nowait - IF INKEY(0.5) = 27 + IF MOD(Recno(), 100) = 0 AND INKEY() = 27 IF AMESSAGEBOX('Doriti sa renuntati?',4+32,_screen.Caption) = 6 llSucces = .F. EXIT @@ -456,6 +548,9 @@ Define Class ExtrasBanca As Custom If !Isnull(loPartener) lnIdPartener = Nvl(loPartener.id_part, 0) lcPartener = Alltrim(Nvl(loPartener.denumire, "")) + If PoateSalvaIbanPePartener(m.lnIdPartener, m.lcIBanPart) + Insert Into cIbanDeSalvat (id_part, iban, denumire) Values (m.lnIdPartener, m.lcIBanPart, m.lcPartener) + ENDIF If GetParteneriByCuiNormalizat(m.lcCodFiscal, "cGrupCuiTemp") And Reccount("cGrupCuiTemp") > 1 lcGrupIdLista = "" Select cGrupCuiTemp @@ -510,12 +605,32 @@ Define Class ExtrasBanca As Custom ENDIF ENDFOR ENDIF && EMPTY(m.lnIdPartener) + IF EMPTY(m.lnIdPartener) + * denumire fara diacritice/punctuatie/forma juridica, cand exacta si permutarile nu gasesc nimic + loPartener = GetPartenerByDenumireNormalizata(m.lcDenumire) + If !Isnull(loPartener) AND !EMPTY(Nvl(loPartener.id_part, 0)) + lnIdPartener = Nvl(loPartener.id_part, 0) + lcPartener = Alltrim(Nvl(loPartener.denumire, "")) + ENDIF + ENDIF + * Partener ambiguu (denumirea gasita se potriveste la mai multi parteneri activi): + * aleg cel cu facturi neachitate pe cont in luna curenta, altfel raman fara partener + IF !EMPTY(m.lnIdPartener) + Select cActTemp + Locate For Upper(Alltrim(cod_fiscal)) = m.lcCodFiscal And Upper(Alltrim(denumire)) = m.lcDenumire + lcTip = Iif(Found(), Alltrim(tip), '') + Select cParteneriTemp + lnIdPartener = AlegePartenerDenumireAmbigua(m.lnIdPartener, m.lcPartener, m.lcTip) + IF EMPTY(m.lnIdPartener) + lcPartener = '' + ENDIF + ENDIF ENDIF * Caut partener dupa IBAN - If Empty(m.lnIdPartener) And !Empty(m.lcIBan) + If Empty(m.lnIdPartener) And !Empty(m.lcIBanPart) Wait Window 'Import inregistrare ' + m.lcRecno + '/' + m.lcRecc + ' - cautare partener IBAN' Nowait - loPartener = GetPartenerByContBanca(m.lcIBAN) + loPartener = GetPartenerByContBanca(m.lcIBanPart) If !Isnull(loPartener) lnIdPartener = Nvl(loPartener.id_part, 0) lcPartener = Alltrim(Nvl(loPartener.denumire, "")) @@ -530,6 +645,10 @@ Define Class ExtrasBanca As Custom AddProperty(loDate, "cod_fiscal", m.lcCodFiscal) AddProperty(loDate, "denumire", m.lcDenumire) AddProperty(loDate, "id_part", m.lnIdPartener) + Select cActTemp + Locate For Upper(Alltrim(cod_fiscal)) = m.lcCodFiscal And Upper(Alltrim(denumire)) = m.lcDenumire + lcTip = Iif(Found(), Alltrim(tip), '') + Select cParteneriTemp lnIdTipPart = Iif(m.lcTip = "D", 17, 16) && furnizor/client AddProperty(loDate, "tip_partener", m.lnIdTipPart) lnTipPersoana = Iif(Len(m.lcCodFiscal) < 13, 1, 2) && persoana juridica/fizica @@ -546,6 +665,30 @@ Define Class ExtrasBanca As Custom ENDSCAN && cParteneriTemp USE IN (SELECT('cParteneriTemp')) + * IBAN tertului (1.3): o singura intrebare pentru toti candidatii adunati in bucla, nu una per rand + If Reccount("cIbanDeSalvat") > 0 + If AMESSAGEBOX('Salvati IBAN-ul pentru ' + Transform(Reccount("cIbanDeSalvat")) + ' parteneri?', 4+32, _screen.Caption) = 6 + Select cIbanDeSalvat + Scan + pcContBancaTert = cIbanDeSalvat.iban + pnIdPartenerTert = cIbanDeSalvat.id_part + goExecutor.oExecuta('UPDATE NOM_PARTENERI SET CONT_BANCA = ?pcContBancaTert WHERE ID_PART = ?pnIdPartenerTert') + Endscan + Endif + Endif + Use In (Select("cIbanDeSalvat")) + + * Curs BNR pe valuta fisierului, pentru randurile fara curs (curs = 0 mai jos) + If !m.llMonedaNationala + PRIVATE pnIdValuta, pdDataMax + pnIdValuta = m.lnIdValuta + Select Max(Data) As maxdata From cActTemp Into Cursor cMaxDataAct + pdDataMax = cMaxDataAct.maxdata + Use In (Select('cMaxDataAct')) + goExecutor.oExecuta('select data, data2, curs, nvl(multiplicator,1) multiplicator from curs' + ; + ' where sters = 0 and id_valuta = ?pnIdValuta and data <= ?pdDataMax order by data desc', 'cCursValuta') + Endif + * Completez conturi, parteneri Select cActTemp lcRecc = Transform(Reccount()) @@ -553,6 +696,14 @@ Define Class ExtrasBanca As Custom lcContD = "" lcContC = "" lnIdPartener = NVL(id_part,0) + * Cheie invatata din istoric, doar cand CUI/denumire/IBAN nu au gasit partenerul (loop-ul anterior) + If Empty(m.lnIdPartener) + lcCheieTxt = Upper(Alltrim(Nvl(explicatie,'')) + ' ' + Alltrim(Nvl(denumire,'')) + ' ' + Alltrim(Nvl(cod_fiscal,''))) + lnIdPartener = CautaPartenerDinIstoric(m.lcCheieTxt) + If !Empty(m.lnIdPartener) + Replace id_part With m.lnIdPartener, partener With GetDenumirePartenerById(m.lnIdPartener), listoric With .T. + Endif + Endif lnIdPartD = 0 lnIdPartC = 0 lcPartD = "" @@ -569,7 +720,7 @@ Define Class ExtrasBanca As Custom Wait Window 'Import inregistrare ' + Transform(Recno()) + '/' + m.lcRecc Nowait IF MOD(m.lnRecno, 100) = 0 - IF INKEY(0.5) = 27 + IF INKEY() = 27 IF AMESSAGEBOX('Doriti sa renuntati?',4+32,_screen.Caption) = 6 llSucces = .F. EXIT @@ -691,82 +842,23 @@ Define Class ExtrasBanca As Custom Replace id_valuta With m.lnIdValuta, nume_val With m.lcNumeValuta If !m.llMonedaNationala IF curs = 0 - REPLACE curs WITH 1 - ENDIF + REPLACE curs WITH CursLaData(Data) + ENDIF Replace suma_val With suma Replace suma With ROUND(suma_val * curs, m.gnPC) Endif - * TODO? - * Intorc cursorul cu facturi al clientului si contului respectiv - * Repet pana la epuizarea sumei de plata/incasare sau pana cand nu mai este sold de imperecheat - * Caut documentele gasite in cursorul cu facturi si imprechez suma pe facturile din cursor - * Daca nu mai am documente, dar suma de plata nu este epuizata, imperechez facturile in ordine cronologica - * Adaug facturile imperecheate - - * Acum asociez doar UN SINGUR DOCUMENT, daca este completat in detaliile operatiei - * Incerc sa aflu documentul pereche dupa cont, partener, suma, numar document doar daca am un singur document!!! daca sunt mai multe se complica cazurile - If This.lFactura && daca este configurata optiunea sa se caute documentele pereche - lcDocumente = Alltrim(NVL(cActTemp.documente,'')) - - * Fortez cautarea chiar daca nu are documente - * Vreau sa gasesc - IF EMPTY(m.lcDocumente) - lcDocumente = '0' - ENDIF - lnSuma = cActTemp.suma - lnDocumente = Getwordcount(m.lcDocumente, ",") - If !Empty(m.lnIdPartener) And m.lnDocumente > 0 - FOR lnDocument = 1 TO m.lnDocumente - lnNrAct = Int(Val(Getwordnum(m.lcDocumente, m.lnDocument, ","))) - Wait Window 'Import inregistrare ' + m.lcRecno + '/' + m.lcRecc + ' - cautare factura: ' + Transform(m.lnNrAct) Nowait - loAct = GetDocumentByContPartenerAct(m.lcContPartener, m.lnIdPartener, m.lnNrAct, .F.) - * daca am gasit un document si suma este mai mica decat soldul facturii (daca erau mai multe documente puteau fi si sume diferite) - If !Empty(m.loAct.id_fact) - Select cActTemp - If m.lcTip = "D" And m.lnSuma <= - m.loAct.solddeb - Replace id_factd With m.loAct.id_fact, pereched With m.loAct.nract, scd With m.loAct.Cont, ascd With m.loAct.acont - Else - If m.lcTip = "C" And m.lnSuma <= m.loAct.solddeb - Replace id_factc With m.loAct.id_fact, perechec With m.loAct.nract, scc With m.loAct.Cont, ascc With m.loAct.acont - Endif - ENDIF - * Daca am gasit un document, ies din bucla - EXIT - Else - lnIdPartAlternativ = 0 - If Used("cGrupParteneriCui") - Select cGrupParteneriCui - Scan For id_part_ales = m.lnIdPartener And id_part <> m.lnIdPartener - lcPartAlternativ = Alltrim(denumire) - loAct = GetDocumentByContPartenerAct(m.lcContPartener, id_part, m.lnNrAct, .F.) - If !Empty(m.loAct.id_fact) And ((m.lcTip = "D" And m.lnSuma <= - m.loAct.solddeb) Or (m.lcTip = "C" And m.lnSuma <= m.loAct.solddeb)) - lnIdPartAlternativ = id_part - Exit - Endif - Select cGrupParteneriCui - Endscan - Endif - Select cActTemp - If !Empty(m.lnIdPartAlternativ) - Select cActTemp - If m.lcTip = "D" - Replace id_factd With m.loAct.id_fact, pereched With m.loAct.nract, scd With m.loAct.Cont, ascd With m.loAct.acont, id_partd With m.lnIdPartAlternativ, partd With m.lcPartAlternativ - Else - Replace id_factc With m.loAct.id_fact, perechec With m.loAct.nract, scc With m.loAct.Cont, ascc With m.loAct.acont, id_partc With m.lnIdPartAlternativ, partc With m.lcPartAlternativ - Endif - EXIT - Endif - ENDIF && !Empty(m.loAct.id_fact) - ENDFOR && lnDocument - ENDIF && !Empty(m.lnIdPartener) And m.lnDocumente > 0 - ENDIF && This.lFactura + * Aloc facturile deschise ale partenerului pe suma randului: numar din text, suma exacta, FIFO, rest pe avans + llAlocatFacturi = .F. + If This.lFactura And !Empty(m.lnIdPartener) And Inlist(m.lcContPartener, '401', '4111') And m.llMonedaNationala + llAlocatFacturi = AlocaFacturiRand(m.lcTip, m.lcContPartener, m.lnIdPartener, m.lcPartener) + Endif * Acum asociez doar UN SINGUR DOCUMENT, daca este completat in detaliile operatiei * Incerc sa aflu documentul pereche dupa cont, partener, suma, numar document doar daca am un singur document!!! daca sunt mai multe se complica cazurile - If This.lComanda && daca este configurata optiunea sa se caute documentele pereche dupa comanda + If This.lComanda And !m.llAlocatFacturi && daca este configurata optiunea sa se caute documentele pereche dupa comanda lcDocumente = Alltrim(cActTemp.comenzi) lnSuma = cActTemp.suma lnDocumente = Getwordcount(m.lcDocumente, ",") @@ -820,7 +912,11 @@ Define Class ExtrasBanca As Custom * Completez acum numar document ca sa pot adauga note de retragere/depunere numerar cu acelasi numar document ca si transferul din banca UPDATE cActTemp SET nr = INT(VAL(DTOS(data) + ALLTRIM(STR(RECNO())))) WHERE EMPTY(NVL(nr,0)) - + + If This.lFactura + ImparteRanduriFacturi() + Endif + * Adaug linii retragere/depunere numerar 5311 = 581 / 581 = 5311 corespunzatoare 581 = 5121 / 5121 = 581 IF m.llSucces SELECT *, -1*RECNO() as nr2 FROM cActTemp WHERE Alltrim(tip_2) = This.cTipDepunere AND (ALLTRIM(scd) = '581' OR ALLTRIM(scc) = '581') INTO CURSOR cNumerarTemp READWRITE @@ -899,13 +995,13 @@ Define Class ExtrasBanca As Custom suma_val, nume_val, id_valuta, Curs, ; Cast(Upper(Alltrim(explicatie) + Iif(!Empty(Nvl(denumire, '')), ' ' + Alltrim(denumire), '') + ; Iif(!Empty(Nvl(cod_fiscal, '')), ' ' + Alltrim(cod_fiscal), '')) As C(100)) As explicatia, ; - M.lcIBAN As explicatia4, ; + Cast(m.lcIBAN As C(100)) As explicatia4, ; scd, scc, ascd, ascc, id_partd, id_partc, partd, partc, ; id_factd, id_factc, pereched, perechec, ; - id_fdoc, fdoc, ; + id_fdoc, fdoc, listoric, ngrupa, npoz, csursa_f, nordine, ; Cast(gnIdSucursala As N(5) Null) As id_sucursala, Space(200) As sucursala ; From cActTemp ; - Order By Data ; + Order By Data, nordine ; Into Cursor cActTemp2 Readwrite * Dadea eroare cand puneam cast(m.gnIdSucursala as I) @@ -921,13 +1017,377 @@ Define Class ExtrasBanca As Custom If Used("cGrupParteneriCui") Use In (Select("cGrupParteneriCui")) Endif + If Used("cCheieInvatata") + Use In (Select("cCheieInvatata")) + Endif + If Used("cSolduriFact") + Use In (Select("cSolduriFact")) + Endif + If Used("cAvansExistent") + Use In (Select("cAvansExistent")) + Endif + If Used("cCursValuta") + Use In (Select("cCursValuta")) + Endif Return m.llSucces Endproc && CreeazaNote + * -------------------------------------------------------------------- + * Cursul pe unitate valabil la tdData, din cCursValuta (incarcat in CreeazaNote): interval exact, + * altfel ultimul curs anterior + avertizare in This.cAvertizareCurs daca e mai vechi de 3 zile; + * fara niciun curs anterior, 1 + avertizare + * -------------------------------------------------------------------- + Procedure CursLaData + Lparameters tdData + Local lnCurs, ldDataCurs, lcData + + lcData = Dtoc(m.tdData) + If !Used('cCursValuta') + Return 1 + Endif + + Select cCursValuta + Locate For m.tdData >= Data And m.tdData <= Data2 + If Found() + Return curs / multiplicator + Endif + + Locate For Data <= m.tdData + If Found() + ldDataCurs = Iif(Vartype(Data) = "T", Ttod(Data), Data) + lnCurs = curs / multiplicator + If m.tdData - m.ldDataCurs > 3 And !(m.lcData $ This.cAvertizareCurs) + This.cAvertizareCurs = This.cAvertizareCurs + Iif(Empty(This.cAvertizareCurs), '', Chr(13)) + ; + m.lcData + ': nu exista curs, s-a folosit cursul din ' + Dtoc(m.ldDataCurs) + Endif + Return m.lnCurs + Endif + + If !(m.lcData $ This.cAvertizareCurs) + This.cAvertizareCurs = This.cAvertizareCurs + Iif(Empty(This.cAvertizareCurs), '', Chr(13)) + ; + m.lcData + ': fara curs, verificati cursul' + Endif + Return 1 + Endproc && CursLaData + Enddefine && ExtrasBanca +* -------------------------------------------------------------------- +* Aloca randul curent din cActTemp (SCAN activ in CreeazaNote) pe facturile deschise ale partenerului, din cSolduriFact: +* N (numar din text) -> S (suma exacta unica) -> F (FIFO) -> A (rest pe avans 419/409, doar pe contul de baza 4111/401) +* Scrie alocarile in cAlocTemp (nrec, npoz, id_fact, nract, cont, acont, suma, csursa); intoarce .T. daca a alocat ceva +* -------------------------------------------------------------------- +Function AlocaFacturiRand + Lparameters tcTip, tcContPartener, tnIdPartener, tcPartener + Local lnRest, lnSuma, lcNumere, lnNpoz, lcContAloc, lcContAvans, llAvansDeschis + Local lnIdPartCandidat, lcPartCandidat, lnRecCrt, lcSelect + + lcSelect = Select() + lnNpoz = 0 + lcContAloc = '' + + If Empty(m.tnIdPartener) Or !Used('cSolduriFact') + Select (m.lcSelect) + Return .F. + Endif + + Select cActTemp + lnRecCrt = Recno() + lnSuma = suma + lnRest = m.lnSuma + lnIdPartCandidat = m.tnIdPartener + lcPartCandidat = m.tcPartener + + lcNumere = ExtrageNumereFacturi(Alltrim(explicatie) + ' ' + Alltrim(Nvl(documente, '')), cod_fiscal, iban) + + * 1. N - numar din text, intai pe partenerul randului, apoi pe cei cu acelasi cod fiscal + If !Empty(m.lcNumere) + AlocaNumarDinText(m.tnIdPartener, m.tcContPartener, m.lcNumere, m.lnRecCrt, @lnRest, @lnNpoz, @lcContAloc) + If m.lnNpoz = 0 And Used('cGrupParteneriCui') + Select cGrupParteneriCui + Scan For id_part_ales = m.tnIdPartener And id_part <> m.tnIdPartener + lnIdPartCandidat = id_part + lcPartCandidat = Alltrim(denumire) + AlocaNumarDinText(m.lnIdPartCandidat, m.tcContPartener, m.lcNumere, m.lnRecCrt, @lnRest, @lnNpoz, @lcContAloc) + If m.lnNpoz > 0 + Exit + Endif + Endscan + If m.lnNpoz = 0 + lnIdPartCandidat = m.tnIdPartener + lcPartCandidat = m.tcPartener + Endif + Endif + Endif + + If m.lnNpoz > 0 And m.lnIdPartCandidat <> m.tnIdPartener + Select cActTemp + Go m.lnRecCrt + If m.tcTip = "D" + Replace id_partd With m.lnIdPartCandidat, partd With m.lcPartCandidat + Else + Replace id_partc With m.lnIdPartCandidat, partc With m.lcPartCandidat + Endif + Endif + + * 2. S - suma exacta unica, doar daca pasul 1 n-a alocat nimic + If m.lnNpoz = 0 + AlocaSumaExacta(m.lnIdPartCandidat, m.tcContPartener, m.lnSuma, m.lnRecCrt, @lnRest, @lnNpoz, @lcContAloc) + Endif + + llAvansDeschis = Used('cAvansExistent') And Seek(m.tnIdPartener, 'cAvansExistent') + + * 3. F - FIFO, doar daca partenerul nu are deja avans deschis (poate fi deja acoperit din avansul necompensat) + If m.lnRest > 0 And !m.llAvansDeschis + AlocaFifo(m.lnIdPartCandidat, m.tcContPartener, m.lnRecCrt, @lnRest, @lnNpoz, @lcContAloc) + Endif + + * 4. A - rest peste facturi: contul de avans se ia dupa contul pe care s-a alocat ultima oara + * (ContAvans - 461/462 nu au avans, ramane fara pereche pe contul randului, ca sa nu se piarda suma din grupa) + If m.lnRest > 0 And m.lnNpoz > 0 + lcContAvans = ContAvans(m.lcContAloc) + lnNpoz = m.lnNpoz + 1 + Insert Into cAlocTemp (nrec, npoz, id_fact, nract, cont, acont, suma, csursa) ; + Values (m.lnRecCrt, m.lnNpoz, 0, 0, Iif(!Empty(m.lcContAvans), m.lcContAvans, m.tcContPartener), "", m.lnRest, "A") + Endif + + Select (m.lcSelect) + Return (m.lnNpoz > 0) +Endfunc + +* -------------------------------------------------------------------- +* Contul de avans pentru contul unei facturi alocate; gol daca acel cont nu are avans (461/462) +* -------------------------------------------------------------------- +Function ContAvans + Lparameters tcCont + Do Case + Case m.tcCont = "4111" + Return "419" + Case m.tcCont = "401" + Return "4091" + Case m.tcCont = "404" + Return "4093" + Otherwise + Return "" + Endcase +Endfunc + +* -------------------------------------------------------------------- +* Candidatii de facturi ai unui partener din cSolduriFact: intai doar tcCont, altfel orice cont al partenerului +* (404/461/462 devin candidati doar prin acest fallback) - cursor cCandRand (nract, dataact, nrecsold), ordonat +* -------------------------------------------------------------------- +Procedure DeschideCandidatiFactura + Lparameters tnIdPart, tcCont + + If Used('cCandRand') + Use In (Select('cCandRand')) + Endif + Select nract, dataact, Recno() As nrecsold ; + From cSolduriFact ; + Where id_part = m.tnIdPart And Alltrim(Cont) = m.tcCont And ramas > 0 ; + Order By dataact, nract ; + Into Cursor cCandRand Readwrite + If Reccount('cCandRand') = 0 + Use In (Select('cCandRand')) + Select nract, dataact, Recno() As nrecsold ; + From cSolduriFact ; + Where id_part = m.tnIdPart And ramas > 0 ; + Order By dataact, nract ; + Into Cursor cCandRand Readwrite + Endif +Endproc + +* -------------------------------------------------------------------- +* Ramasul curent (live) al unei facturi din cSolduriFact, dupa recno-ul ei +* -------------------------------------------------------------------- +Function RamasFactura + Lparameters tnRecSold + Local lnRamas, lcSelect + + lcSelect = Select() + lnRamas = 0 + Select cSolduriFact + Try + Go m.tnRecSold + lnRamas = ramas + Catch + Endtry + Select (m.lcSelect) + Return m.lnRamas +Endfunc + +* -------------------------------------------------------------------- +* Scrie o alocare in cAlocTemp, scade ramas-ul facturii si actualizeaza rest/npoz/contul alocat ale randului +* -------------------------------------------------------------------- +Procedure AplicaAlocareFactura + Lparameters tnRecCrt, tnRecSold, tcSursa, tnRest, tnNpoz, tcContAloc + Local lnAlocat, lcSelect, lnIdFact, lnNract, lcCont, lcAcont + + lcSelect = Select() + Select cSolduriFact + Try + Go m.tnRecSold + Catch + Select (m.lcSelect) + Return + Endtry + + lnAlocat = Min(m.tnRest, ramas) + lnIdFact = id_fact + lnNract = nract + lcCont = Alltrim(Cont) + lcAcont = acont + tnNpoz = m.tnNpoz + 1 + * campurile sursa (cSolduriFact) copiate in variabile - Insert Into rezolva numele necalificate pe cursorul tinta, nu pe cel curent + Insert Into cAlocTemp (nrec, npoz, id_fact, nract, cont, acont, suma, csursa) ; + Values (m.tnRecCrt, m.tnNpoz, m.lnIdFact, m.lnNract, m.lcCont, m.lcAcont, m.lnAlocat, m.tcSursa) + Replace ramas With ramas - m.lnAlocat + tnRest = m.tnRest - m.lnAlocat + tcContAloc = m.lcCont + + Select (m.lcSelect) +Endproc + +* -------------------------------------------------------------------- +* N - aloca facturile al caror numar apare in text (lista tcNumere, separata prin virgula) +* -------------------------------------------------------------------- +Procedure AlocaNumarDinText + Lparameters tnIdPart, tcCont, tcNumere, tnRecCrt, tnRest, tnNpoz, tcContAloc + + DeschideCandidatiFactura(m.tnIdPart, m.tcCont) + Select cCandRand + Scan For (',' + Transform(nract) + ',') $ (',' + m.tcNumere + ',') + If m.tnRest <= 0 + Exit + Endif + If RamasFactura(nrecsold) > 0 + AplicaAlocareFactura(m.tnRecCrt, nrecsold, "N", @tnRest, @tnNpoz, @tcContAloc) + Endif + Endscan + Use In (Select('cCandRand')) +Endproc + +* -------------------------------------------------------------------- +* S - aloca integral daca exista exact un candidat al carui ramas este egal cu suma randului +* -------------------------------------------------------------------- +Procedure AlocaSumaExacta + Lparameters tnIdPart, tcCont, tnSuma, tnRecCrt, tnRest, tnNpoz, tcContAloc + Local lnCandidati, lnRecPotrivit + + DeschideCandidatiFactura(m.tnIdPart, m.tcCont) + lnCandidati = 0 + lnRecPotrivit = 0 + Select cCandRand + Scan + If RamasFactura(nrecsold) = m.tnSuma + lnCandidati = m.lnCandidati + 1 + lnRecPotrivit = nrecsold + Endif + Endscan + If m.lnCandidati = 1 + AplicaAlocareFactura(m.tnRecCrt, m.lnRecPotrivit, "S", @tnRest, @tnNpoz, @tcContAloc) + Endif + Use In (Select('cCandRand')) +Endproc + +* -------------------------------------------------------------------- +* F - aloca in ordine cronologica pana la epuizarea sumei (ultima factura poate ramane platita partial) +* -------------------------------------------------------------------- +Procedure AlocaFifo + Lparameters tnIdPart, tcCont, tnRecCrt, tnRest, tnNpoz, tcContAloc + + DeschideCandidatiFactura(m.tnIdPart, m.tcCont) + Select cCandRand + Scan + If m.tnRest <= 0 + Exit + Endif + If RamasFactura(nrecsold) > 0 + AplicaAlocareFactura(m.tnRecCrt, nrecsold, "F", @tnRest, @tnNpoz, @tcContAloc) + Endif + Endscan + Use In (Select('cCandRand')) +Endproc + +* -------------------------------------------------------------------- +* Numere de document din text (explicatie+documente), cifre lungi de minim 3, fara cod_fiscal/iban +* -------------------------------------------------------------------- +Function ExtrageNumereFacturi + Lparameters tcTexte, tcCodFiscal, tcIban + Local lcTexte, lcNumere, lcRezultat, lnI, lcNumar + + lcTexte = Upper(Alltrim(Nvl(m.tcTexte, ''))) + If !Empty(Nvl(m.tcCodFiscal, '')) + lcTexte = Strtran(m.lcTexte, Upper(Alltrim(m.tcCodFiscal)), ' ') + Endif + If !Empty(Nvl(m.tcIban, '')) + lcTexte = Strtran(m.lcTexte, Upper(Alltrim(m.tcIban)), ' ') + Endif + + lcNumere = '' + GetRegExpAllNumbers(m.lcTexte, @lcNumere) + + lcRezultat = '' + For lnI = 1 To Getwordcount(m.lcNumere, ',') + lcNumar = Alltrim(Getwordnum(m.lcNumere, m.lnI, ',')) + If Len(m.lcNumar) >= 3 + lcRezultat = m.lcRezultat + Iif(!Empty(m.lcRezultat), ',', '') + m.lcNumar + Endif + Endfor + + Return m.lcRezultat +Endfunc + +* -------------------------------------------------------------------- +* Transforma alocarile din cAlocTemp in randuri suplimentare in cActTemp (ngrupa/npoz/csursa_f/nordine) +* Alocarea 1 se scrie pe randul original, urmatoarele se adauga la coada prin Append+Gather +* -------------------------------------------------------------------- +Procedure ImparteRanduriFacturi + Local lnRecCrt, loR + + If !Used('cAlocTemp') Or Reccount('cAlocTemp') = 0 + Return + Endif + + Select cActTemp + Replace All nordine With Recno() * 100 + + Select cAlocTemp + Index On nrec * 1000 + npoz Tag ordine + Set Order To ordine + Go Top + + lnRecCrt = 0 + Scan + Select cActTemp + If cAlocTemp.nrec <> m.lnRecCrt + lnRecCrt = cAlocTemp.nrec + Try + Go m.lnRecCrt + Catch + Loop + Endtry + Scatter Memo Name loR + Else + Append Blank + Gather Memo Name loR + Endif + + If Alltrim(loR.tip) = "D" + Replace scd With cAlocTemp.Cont, ascd With cAlocTemp.acont, id_factd With cAlocTemp.id_fact, pereched With cAlocTemp.nract + Else + Replace scc With cAlocTemp.Cont, ascc With cAlocTemp.acont, id_factc With cAlocTemp.id_fact, perechec With cAlocTemp.nract + Endif + Replace suma With cAlocTemp.suma, ngrupa With m.lnRecCrt, npoz With cAlocTemp.npoz, ; + csursa_f With cAlocTemp.csursa, nordine With m.lnRecCrt * 100 + cAlocTemp.npoz + Endscan + + Use In (Select('cAlocTemp')) +Endproc + + Define Class ExtrasBanca_MT940 As ExtrasBanca cDescription = 'clasa generica import extras MT940' @@ -938,10 +1398,12 @@ Define Class ExtrasBanca_MT940 As ExtrasBanca Local lcBanca, lcCodFiscal, lcCursor, lcDenumire, lcDescriere, lcExtraRand, lcFacturi, lcFile Local lcIBAN, lcRand, lcRand1, lcRefDoc, lcTip, lcTip2, ldData, lnLinie, lnLinii, lnNr, lnPos - Local lnPozitieN, lnRand, lnResults, lnSuma, llSucces + Local lnPozitieN, lnRand, lnResults, lnSuma, llSucces, lcIBANPrim, llIbanMultiplu lcFile = This.cFile lnLinii = 0 + llIbanMultiplu = .F. + lcIBANPrim = '' If File(m.lcFile) lnLinii = Alines(This.aLinii, Filetostr(m.lcFile), 1) lnLinii = Iif(Empty(m.lnLinii), 0, m.lnLinii) @@ -987,11 +1449,26 @@ Define Class ExtrasBanca_MT940 As ExtrasBanca * :25:RO57RZBR0000060011634808 This.cIBAN = Upper(Alltrim(Substr(m.lcRand, 5))) && RO57RZBR0000060011634808 This.cBIC = Substr(m.lcRand, 9, 4) && RZBR + If Empty(m.lcIBANPrim) + lcIBANPrim = This.cIBAN + Else + If This.cIBAN <> m.lcIBANPrim + llIbanMultiplu = .T. + Endif + Endif Case Left(m.lcRand, 5) = ':28C:' && numar extras/statement number * :28C:213/1 This.nNr = Int(Val(Substr(m.lcRand, 6))) && 213 + Case Inlist(Left(m.lcRand, 5), ':60F:', ':60M:') && sold initial, primul gasit + If Isnull(This.nSoldInitial) + This.nSoldInitial = SoldMT940(m.lcRand) + Endif + + Case Inlist(Left(m.lcRand, 5), ':62F:', ':62M:') && sold final, ultimul gasit + This.nSoldFinal = SoldMT940(m.lcRand) + Case Left(m.lcRand, 4) = ':61:' && tranzactie master, pe un singur rand * :61:1712201220D82665,12NTRF32871258//3A9H3KUEDK5T72I * :61:1712201220D3141,04NTRFNONREF//3A9H3KUEDK5T73M @@ -1060,6 +1537,11 @@ Define Class ExtrasBanca_MT940 As ExtrasBanca Select C_IMPORT_TEMP Replace All nr With This.nNr For Empty(nr) + + If m.llIbanMultiplu + This.nSoldInitial = .Null. + This.nSoldFinal = .Null. + Endif Endif && llSucces Return m.llSucces @@ -1165,6 +1647,8 @@ Define Class ExtrasBanca_CREDITEUROPE_XML As ExtrasBanca This.cIBAN = Upper(Alltrim(Strextract(m.lcInfo1, '', '', 1, 1))) This.cValuta = Upper(Alltrim(Strextract(m.lcInfo1, '', '', 1, 1))) + This.nSoldInitial = Val(Strextract(m.lcInfo1, '', '', 1, 1)) + This.nSoldFinal = Val(Strextract(m.lcInfo2, '', '', 1, 1)) If !Inlist(This.cValuta, 'RON', 'LEI', 'ROL') This.cContBanca = '5124' && banca valuta Endif @@ -1316,6 +1800,8 @@ Cont;Suma;Valuta;Data tranzactiei;Data valutei;Banca;Numele bancii;Adresa bancii lcLinie = This.aLinii[2] This.cIBAN = syGETWORDNUM(m.lcLinie, 2, ';') This.cValuta = syGETWORDNUM(m.lcLinie, 3, ';') + This.nSoldInitial = Val(Strtran(Strtran(syGETWORDNUM(m.lcLinie, 4, ';'), '.', '', 1, 10, 1), ',', '.', 1, 1, 1)) + This.nSoldFinal = Val(Strtran(Strtran(syGETWORDNUM(m.lcLinie, 5, ';'), '.', '', 1, 10, 1), ',', '.', 1, 1, 1)) This.nNr = Int(Val(Dtos(Gomonth(Date(m.gnAn, m.gnLuna, 1), 1) - 1))) @@ -1433,7 +1919,7 @@ Define Class ExtrasBanca_General As ExtrasBanca If !Inlist(Upper(Justext(mSelectedFile)), "XLS", "XML") lnfilehandle = Fopen(mSelectedFile) If lnfilehandle = -1 - Messagebox( "Fisierul nu poate fi accesat." + Chr(13) + "Probabil ca este deschis �n alta fereastra.", 16, "Eroare acces" ) + Messagebox( "Fisierul nu poate fi accesat." + Chr(13) + "Probabil ca este deschis in alta fereastra.", 16, "Eroare acces" ) Return .F. Endif Do While !Feof(lnfilehandle) .And. Empty(mrand) @@ -1455,7 +1941,8 @@ Define Class ExtrasBanca_General As ExtrasBanca * Data Comenzii,Tipul,Nr Comanda,,Data Transferului,Suma,Comision,Suma Neta,Referinta This.csvStripe(mSelectedFile) Case Lower(Left(mrand, 4)) = "tip," .Or. Lower(Left(mrand, 5)) = "type," - This.csvBooking(mSelectedFile) + Messagebox( "Formatul fisierului CSV nu este implementat pentru import.", 16, "Format necunoscut" ) + Return .F. Case "id produs,cod produs," $ Lower(mrand) This.csvPayu(mSelectedFile) Case Occurs('textbox', Lower(mrand)) > 6 @@ -1469,11 +1956,14 @@ Define Class ExtrasBanca_General As ExtrasBanca Case 'awb,data_awb,destinatar' $ Lower(mrand) This.csvFunCourier2(mSelectedFile) Case 'idawb' $ Lower(mrand) - This.csvCargus(mSelectedFile) + Messagebox( "Formatul fisierului CSV nu este implementat pentru import.", 16, "Format necunoscut" ) + Return .F. Case 'waybill' $ Lower(mrand) - This.csvDPD(mSelectedFile, 1) + Messagebox( "Formatul fisierului CSV nu este implementat pentru import.", 16, "Format necunoscut" ) + Return .F. Case 'data,id,numar' $ Lower(mrand) .Or. '"data","id","numar"' $ Lower(mrand) .Or. 'data;id;numar' $ Lower(mrand) .Or. '"data";"id";"numar"' $ Lower(mrand) - This.csvDPD(mSelectedFile, 2) + Messagebox( "Formatul fisierului CSV nu este implementat pentru import.", 16, "Format necunoscut" ) + Return .F. Case 'tranzactiile contului:' $ Lower(mrand) .Or. 'account activities:' $ Lower(mrand) This.csvGaranti(mSelectedFile) Case Lower(Left(mrand, 11)) = "cod client:" @@ -1520,9 +2010,11 @@ Define Class ExtrasBanca_General As ExtrasBanca Case "data emitere extras" $ Lower(mrand) This.csvBCR(mSelectedFile) Case Occurs(";", mrand) = 7 - This.csvUnDoi(mSelectedFile) + Messagebox( "Formatul fisierului CSV nu este implementat pentru import.", 16, "Format necunoscut" ) + Return .F. Case Occurs(",", mrand) = 6 - This.csvPaypoint(mSelectedFile) + Messagebox( "Formatul fisierului CSV nu este implementat pentru import.", 16, "Format necunoscut" ) + Return .F. Case "platitor_nume_denumire" $ Lower(mrand) This.csvIdea(mSelectedFile) Case "numeclient,perioada,codclient" $ Lower(mrand) @@ -1561,8 +2053,14 @@ Define Class ExtrasBanca_General As ExtrasBanca Function MT940 - Fopen(mSelectedFile) + Lparameters mSelectedFile + lnfilehandle = Fopen(mSelectedFile) mtextoriginal = "" + mibanprim = '' + mibanmultiplu = .F. + isfaracitire = .F. + isbcr = .F. + isunicredit = .F. Select c_iex Do While !Feof(lnfilehandle) If !isfaracitire @@ -1573,6 +2071,19 @@ Define Class ExtrasBanca_General As ExtrasBanca Case Left(m.mrand, 4) = ':25:' && cont bancar * :25:RO57RZBR0000060011634808 This.cIBAN = Upper(Alltrim(Substr(m.mrand, 5))) && RO57RZBR0000060011634808 + If Empty(mibanprim) + mibanprim = This.cIBAN + Else + If This.cIBAN <> mibanprim + mibanmultiplu = .T. + Endif + Endif + Case Inlist(Left(m.mrand, 5), ':60F:', ':60M:') && sold initial, primul gasit + If Isnull(This.nSoldInitial) + This.nSoldInitial = SoldMT940(m.mrand) + Endif + Case Inlist(Left(m.mrand, 5), ':62F:', ':62M:') && sold final, ultimul gasit + This.nSoldFinal = SoldMT940(m.mrand) Case ":61:" $ mrand Append Blank mldatae = {} @@ -1809,6 +2320,10 @@ Define Class ExtrasBanca_General As ExtrasBanca Replace original With mtextoriginal Enddo Fclose(lnfilehandle) + If mibanmultiplu + This.nSoldInitial = .Null. + This.nSoldFinal = .Null. + Endif Endfunc Function xlsGeneral @@ -1898,7 +2413,7 @@ Define Class ExtrasBanca_General As ExtrasBanca mdataextras = m.lcData Endif - Case Inlist(Lower(Left(m.lcValue, 5)), "numar", "num�r") + Case Inlist(Lower(Left(m.lcValue, 5)), "numar", "numãr") mnrstart = RECNO() Exit Endcase @@ -1975,7 +2490,7 @@ Define Class ExtrasBanca_General As ExtrasBanca *!* CASE "cont bancar nr.:" $ m.lcValue *!* This.cIBAN = UPPER(ALLTRIM(SUBSTR(m.lcValue, 17))) - Case Inlist(Lower(Left(m.lcValue, 5)), "numar", "num�r") + Case Inlist(Lower(Left(m.lcValue, 5)), "numar", "numãr") mnrstart = I Exit @@ -2050,7 +2565,7 @@ Define Class ExtrasBanca_General As ExtrasBanca Endif I = I + 1 Enddo - Case m.llXLS AND (Type( "oExcelApp.Cells(5,1).Value" ) = "C" .And. Lower(Left(oexcelapp.cells(5, 1).Value, 20)) = "soldul depus �nainte") + Case m.llXLS AND (Type( "oExcelApp.Cells(5,1).Value" ) = "C" .And. Lower(Left(oexcelapp.cells(5, 1).Value, 20)) = "soldul depus înainte") mtipimport = "Viva" I = 6 Do While !Isnull(oexcelapp.cells(I, 1).Value) .And. !Empty(oexcelapp.cells(I, 1).Value) @@ -2516,6 +3031,14 @@ Define Class ExtrasBanca_General As ExtrasBanca Endif Do Case Case orootnode.nodename = "document" + loNodSold = oxml.selectSingleNode('//opening_balance/balance') + If !Isnull(loNodSold) + This.nSoldInitial = Val(loNodSold.Text) + Endif + loNodSold = oxml.selectSingleNode('//closing_balance/balance') + If !Isnull(loNodSold) + This.nSoldFinal = Val(loNodSold.Text) + Endif orootnodecontext = orootnode.childnodes.Item(2) If orootnodecontext.nodename <> "movements" Messagebox( "Format XML invalid.", 64, "Atentie...") @@ -2926,18 +3449,29 @@ Define Class ExtrasBanca_General As ExtrasBanca * tnTip: 1 (default) = lista tranzactii, 2 = extras de cont Local mtextoriginal - Local lcDescriereFacturi, lcFacturi, lcLinie, lnLinie, lnLinii, lnResults + Local lcComerciant, lcDescriereFacturi, lcFacturi, lcLinie, lnLinie, lnLinii, lnResults LOCAL mcf, mexplicatie, mfilestr, miban, mtert lnLinii = Alines(This.aLinii, Filetostr(m.pselectedfile), 1) FOR lnLinie = 1 TO lnLinii lcLinie = This.aLinii[m.lnLinie] lcItem = STRTRAN(LOWER(ALLTRIM(GETWORDNUM(m.lcLinie,1,','))), ["], [],1,2) - IF m.lcItem = [numar cont:] - This.cIBAN = STRTRAN(LEFT(ALLTRIM(syGETWORDNUM(m.lcLinie, 2, ',')), 24), ["], [], 1, 2) - EXIT - ENDIF - ENDFOR + DO CASE + CASE m.lcItem = [numar cont:] + This.cIBAN = STRTRAN(LEFT(ALLTRIM(syGETWORDNUM(m.lcLinie, 2, ',')), 24), ["], [], 1, 2) + IF m.tnTip = 1 && Tip B: "RO32...701 RON" + This.cValuta = ALLTRIM(syGETWORDNUM(ALLTRIM(syGETWORDNUM(m.lcLinie, 2, ',')), 2, ' ')) + ENDIF + CASE m.lcItem = [moneda cont:] && Tip A + This.cValuta = ALLTRIM(syGETWORDNUM(m.lcLinie, 2, ',')) + CASE m.lcItem = [sold initial:] + This.nSoldInitial = VAL(syGETWORDNUM(m.lcLinie, 2, ',')) + CASE m.lcItem = [sold final cont:] + This.nSoldFinal = VAL(syGETWORDNUM(m.lcLinie, 2, ',')) + CASE m.lcItem = [data tranzactie] && capul tabelului de tranzactii + EXIT + ENDCASE + ENDFOR IF EMPTY(this.cIBAN) This.cIBAN = 'BT' @@ -2968,6 +3502,27 @@ Define Class ExtrasBanca_General As ExtrasBanca Strtofile(mfilestr, m.gcTempPath + "BTTMP.csv") Append From (m.gcTempPath + "BTTMP.csv") Csv + IF m.tnTip = 1 AND Reccount() > 0 && Sold contabil pe rand, descrescator: primul da SF, ultimul da SI (invers daca fisierul e crescator) + Go Top + ldDataPrim = setdategerman(Alltrim(data_t)) + lnSoldPrim = This.setsuma(sold) + lnDPrim = This.setsuma(suma_d) + lnCPrim = This.setsuma(suma_c) + Go Bottom + ldDataUlt = setdategerman(Alltrim(data_t)) + lnSoldUlt = This.setsuma(sold) + lnDUlt = This.setsuma(suma_d) + lnCUlt = This.setsuma(suma_c) + IF m.ldDataPrim >= m.ldDataUlt + This.nSoldFinal = m.lnSoldPrim + This.nSoldInitial = m.lnSoldUlt - m.lnCUlt - m.lnDUlt + ELSE + This.nSoldInitial = m.lnSoldPrim - m.lnCPrim - m.lnDPrim + This.nSoldFinal = m.lnSoldUlt + ENDIF + Go Top + ENDIF + Scan For !Empty(data_t) .And. !Empty(setdategerman(C_TMP_I.data_t)) Select c_iex Insert Into c_iex (Data) Values (setdategerman(Alltrim(C_TMP_I.data_t))) @@ -2999,7 +3554,8 @@ Define Class ExtrasBanca_General As ExtrasBanca Case LEFT(ALLTRIM(LOWER(NVL(mexplicatie,''))), 8) = "comision" OR ; 'comision-atm'$LOWER(NVL(mexplicatie,'')) OR ; 'comision procesare ridicare numerar'$LOWER(NVL(mexplicatie,'')) OR ; - 'pachet izi'$LOWER(NVL(mexplicatie,'')) + 'pachet izi'$LOWER(NVL(mexplicatie,'')) OR ; + 'pachet pj'$LOWER(NVL(mexplicatie,'')) Replace tip_2 With This.cTipComisioane Case 'retragere de numerar'$ALLTRIM(LOWER(NVL(mexplicatie,''))) @@ -3013,11 +3569,30 @@ Define Class ExtrasBanca_General As ExtrasBanca mtert = ALLTRIM(syGETWORDNUM(m.mexplicatie, 3, ';')) miban = ALLTRIM(syGETWORDNUM(m.mexplicatie, 4, ';')) mcf = "" + IF "C.I.F.:" $ m.mexplicatie + mcf = getdigitsfromstring(Alltrim(Substr(m.mexplicatie, At("C.I.F.:", m.mexplicatie) + 7, 13)), 4, 1, ".") + IF Alltrim(mcf) == Alltrim(gofirma.codfiscalfro) + mcf = "" + ENDIF + ENDIF lcDescriereFacturi = ALLTRIM(syGETWORDNUM(m.mexplicatie, 2, ';')) lcFacturi = '' lnResults = GetRegExpAllNumbers(m.lcDescriereFacturi, @m.lcFacturi) + IF "TID:" $ m.lcDescriereFacturi AND "valoare tranzactie:" $ m.lcDescriereFacturi + * comerciantul din textul EPOS, nu titularul contului propriu + lcComerciant = Substr(m.lcDescriereFacturi, At("TID:", m.lcDescriereFacturi) + 4) + lcComerciant = Substr(lcComerciant, At(" ", lcComerciant) + 1) + lcComerciant = Alltrim(Substr(lcComerciant, 1, At("valoare tranzactie:", lcComerciant) - 1)) + Do While !Empty(lcComerciant) And Isdigit(Right(lcComerciant, 1)) + lcComerciant = Alltrim(Left(lcComerciant, Rat(" ", lcComerciant))) + Enddo + IF !Empty(lcComerciant) + mtert = lcComerciant + ENDIF + ENDIF + Replace tert With mtert, iban With miban, cf With mcf, documente WITH m.lcFacturi mtextoriginal = C_TMP_I.data_t + " " + Chr(13) + Alltrim(C_TMP_I.suma_d) + "," + Alltrim(C_TMP_I.suma_c) + " " + Chr(13) + Alltrim(mexplicatie) Replace explicatie With mexplicatie, original With mtextoriginal @@ -3985,13 +4560,15 @@ Define Class ExtrasBanca_General As ExtrasBanca If File(m.pselectedfile) - lnLinii = Alines(This.aLinii, Filetostr(m.lcFile), 1) + lnLinii = Alines(This.aLinii, Filetostr(m.pselectedfile), 1) lnLinii = Iif(Empty(m.lnLinii), 0, m.lnLinii) This.nLinii = m.lnLinii lcLinie = This.aLinii[2] This.cIBAN = syGETWORDNUM(m.lcLinie, 2, ';') This.cValuta = syGETWORDNUM(m.lcLinie, 3, ';') + This.nSoldInitial = Val(Strtran(Strtran(syGETWORDNUM(m.lcLinie, 4, ';'), '.', '', 1, 10, 1), ',', '.', 1, 1, 1)) + This.nSoldFinal = Val(Strtran(Strtran(syGETWORDNUM(m.lcLinie, 5, ';'), '.', '', 1, 10, 1), ',', '.', 1, 1, 1)) Endif Do Case @@ -4250,6 +4827,215 @@ Function verifcf Endif Endfunc * +Function NormalizeazaDenumire + Lparameters tcDenumire + Local lcD, lcUltimulCuvant + lcD = Alltrim(Nvl(m.tcDenumire, "")) + lcD = Strtran(Strtran(Strtran(Strtran(lcD, Chr(195), "A"), Chr(227), "A"), Chr(194), "A"), Chr(226), "A") + lcD = Strtran(Strtran(lcD, Chr(206), "I"), Chr(238), "I") + lcD = Strtran(Strtran(lcD, Chr(170), "S"), Chr(186), "S") + lcD = Strtran(Strtran(lcD, Chr(222), "T"), Chr(254), "T") + lcD = Upper(Strtran(lcD, ".", "")) + lcD = Strtran(Strtran(lcD, ",", " "), "-", " ") + Do While " " $ lcD + lcD = Strtran(lcD, " ", " ") + Enddo + lcD = Alltrim(lcD) + lcUltimulCuvant = Getwordnum(lcD, Getwordcount(lcD)) + IF Inlist(lcUltimulCuvant, "SRL", "SA", "PFA", "II", "IF", "SNC", "SCS") AND Getwordcount(lcD) > 1 + lcD = Alltrim(Substr(lcD, 1, Len(lcD) - Len(lcUltimulCuvant))) + ENDIF + IF Getwordnum(lcD, 1) == "SC" AND Getwordcount(lcD) > 1 + lcD = Alltrim(Substr(lcD, At(" ", lcD) + 1)) + ENDIF + Return lcD +Endfunc +* +* -------------------------------------------------------------------- +* Cauta partenerul dupa denumire normalizata (fara diacritice/punctuatie/forma juridica) +* -------------------------------------------------------------------- +Function GetPartenerByDenumireNormalizata + Lparameters tcDenumire + Private pcDenumireLike + Local lcDenNorm, lcSql, llSucces, loPartener + loPartener = NULL + lcDenNorm = NormalizeazaDenumire(m.tcDenumire) + IF Empty(m.lcDenNorm) OR Len(Getwordnum(m.lcDenNorm, 1)) < 3 + Return loPartener + ENDIF + * prefiltru: rateaza candidatul daca primul cuvant din denumirea din baza are diacritice (LIKE e pe coloana bruta, nu normalizata) + pcDenumireLike = "%" + Alltrim(Getwordnum(m.lcDenNorm, 1)) + "%" + lcSql = [select id_part, denumire from nom_parteneri where sters = 0 and inactiv = 0 ] + ; + [and upper(denumire) like ?pcDenumireLike order by id_part] + llSucces = goExecutor.oExecuta(m.lcSql, "cDenNormTemp") + IF m.llSucces + Select cDenNormTemp + Scan + IF NormalizeazaDenumire(denumire) == m.lcDenNorm + loPartener = Createobject("Empty") + AddProperty(loPartener, "id_part", id_part) + AddProperty(loPartener, "denumire", Alltrim(Nvl(denumire, ""))) + EXIT + ENDIF + Endscan + Use In (Select("cDenNormTemp")) + ENDIF + Return loPartener +Endfunc +* +* -------------------------------------------------------------------- +* Contul IBAN al unui procesator de plati/Trezorerie/curier, care nu se salveaza pe partener +* -------------------------------------------------------------------- +Function EsteIbanInListaNeagra + Lparameters tcIban + Local lcIban + lcIban = Upper(Chrtran(Alltrim(Nvl(m.tcIban, '')), ' ', '')) + If Len(m.lcIban) < 8 + Return .F. + Endif + * codul de banca al Trezoreriei Statului ocupa pozitiile 5-8 din IBAN + If Substr(m.lcIban, 5, 4) == 'TREZ' + Return .T. + Endif + Return .F. +Endfunc +* +* -------------------------------------------------------------------- +* Garda E3: salveaza IBAN-ul tertului pe partener doar daca partenerul nu are deja un cont, +* IBAN-ul nu e deja pe alt partener activ si nu e din lista neagra +* -------------------------------------------------------------------- +Function PoateSalvaIbanPePartener + Lparameters tnIdPartener, tcIban + Private pnIdPartener, pcIban + Local lcSql, lnExistent + + If Empty(m.tnIdPartener) Or Empty(m.tcIban) Or EsteIbanInListaNeagra(m.tcIban) + Return .F. + Endif + pnIdPartener = m.tnIdPartener + pcIban = Upper(Chrtran(Alltrim(m.tcIban), ' ', '')) + + lnExistent = 0 + lcSql = [select count(*) as nr from nom_parteneri where id_part = ?pnIdPartener ] + ; + [and cont_banca is not null and trim(cont_banca) <> ''] + If goExecutor.oSelect2Value(m.lcSql, @lnExistent) < 0 Or m.lnExistent > 0 + Return .F. && partenerul are deja un cont bancar salvat + Endif + + lnExistent = 0 + lcSql = [select count(*) as nr from nom_parteneri where trim(upper(cont_banca)) = ?pcIban ] + ; + [and id_part <> ?pnIdPartener and sters = 0 and inactiv = 0] + If goExecutor.oSelect2Value(m.lcSql, @lnExistent) < 0 Or m.lnExistent > 0 + Return .F. && contul e deja pe alt partener + Endif + + Return .T. +Endfunc +* +* -------------------------------------------------------------------- +* Cand denumirea gasita se potriveste la mai multi parteneri activi, alege cel cu facturi +* neachitate pe cont (luna curenta); daca niciunul sau mai multi au, intoarce 0 (necompletat) +* -------------------------------------------------------------------- +Function AlegePartenerDenumireAmbigua + Lparameters tnIdPartener, tcDenumire, tcTip + Private pcDenumire, pcCont + Local lcSql, llSucces, lcGrupIdLista, lnRezultat + + pcDenumire = Upper(Alltrim(m.tcDenumire)) + pcCont = Iif(Upper(Alltrim(m.tcTip)) = "D", "401", "4111") + + lcSql = [select id_part from nom_parteneri where trim(upper(denumire)) = ?pcDenumire and sters = 0 and inactiv = 0] + llSucces = goExecutor.oExecuta(m.lcSql, "cDenumireAmbigua") + If !m.llSucces Or Reccount("cDenumireAmbigua") <= 1 + If Used("cDenumireAmbigua") + Use In (Select("cDenumireAmbigua")) + Endif + Return m.tnIdPartener + Endif + + lcGrupIdLista = "" + Select cDenumireAmbigua + Scan + lcGrupIdLista = m.lcGrupIdLista + Iif(Empty(m.lcGrupIdLista), "", ",") + Transform(id_part) + Endscan + Use In (Select("cDenumireAmbigua")) + + lcSql = [select p.id_part from nom_parteneri p where p.sters = 0 and p.inactiv = 0 and p.id_part in (] + m.lcGrupIdLista + [) ] + ; + [and exists (select 1 from ireg_parteneri i where i.an = ?gnAn and i.luna = ?gnLuna ] + ; + [and i.id_part = p.id_part and i.cont = ?pcCont ] + ; + [and (i.precdeb + i.debit - i.preccred - i.credit) <> 0)] + llSucces = goExecutor.oExecuta(m.lcSql, "cCuFacturi") + lnRezultat = 0 + If m.llSucces And Reccount("cCuFacturi") = 1 + Select cCuFacturi + lnRezultat = id_part + Endif + If Used("cCuFacturi") + Use In (Select("cCuFacturi")) + Endif + Return m.lnRezultat +Endfunc +* +* -------------------------------------------------------------------- +* Text normalizat pentru cheia invatata din istoric: fara diacritice/punctuatie/forma juridica +* (NormalizeazaDenumire), fara cuvinte scurte/cu cifre (sume, date, numere de document, referinte) - +* denumirea e la coada textului ('explicatie+denumire+cod_fiscal', OPI CreeazaNote), deci iau +* ultimele 3 cuvinte utile ramase, nu primele (primele sunt aproape mereu referinta operatiei) +* -------------------------------------------------------------------- +Function TextIstoricNormalizat + Lparameters tcText + Local lcD, lcTok, lcRez, lnW, lnI, lnUtile + Dimension laUtile(1) + lcD = NormalizeazaDenumire(m.tcText) + lnUtile = 0 + lnW = Getwordcount(m.lcD) + For lnI = 1 To m.lnW + lcTok = Getwordnum(m.lcD, m.lnI) + If Len(m.lcTok) >= 3 And Chrtran(m.lcTok, '0123456789', '') == m.lcTok + lnUtile = m.lnUtile + 1 + Dimension laUtile(m.lnUtile) + laUtile(m.lnUtile) = m.lcTok + Endif + Endfor + * sufix juridic ramas la coada (dupa ce cifrele/referintele au fost deja scoase) + If m.lnUtile > 0 And Inlist(laUtile(m.lnUtile), "SRL", "SA", "PFA", "II", "IF", "SNC", "SCS") + lnUtile = m.lnUtile - 1 + Endif + If m.lnUtile < 2 + Return '' + Endif + lcRez = '' + For lnI = Max(1, m.lnUtile - 2) To m.lnUtile + lcRez = m.lcRez + Iif(Empty(m.lcRez), '', ' ') + laUtile(m.lnI) + Endfor + Return m.lcRez +Endfunc +* +* -------------------------------------------------------------------- +* Cauta id_part in cursorul cCheieInvatata (construit o singura data per import) dupa cheia +* invatata din textul brut al liniei curente; 0 daca cursorul lipseste sau cheia nu e cunoscuta +* -------------------------------------------------------------------- +Function CautaPartenerDinIstoric + Lparameters tcTextBrut + Local lcCheie + If !Used("cCheieInvatata") + Return 0 + Endif + lcCheie = TextIstoricNormalizat(m.tcTextBrut) + If Empty(m.lcCheie) + Return 0 + Endif + If Seek(m.lcCheie, "cCheieInvatata", "cheie") + Return cCheieInvatata.id_part + Endif + Return 0 +Endfunc +* +Function SoldMT940 + Lparameters tcRand + Return Iif(Substr(m.tcRand, 6, 1) = 'D', -1, 1) * Val(Strtran(Substr(m.tcRand, 16), ',', '.')) +Endfunc +* Function getnrfromstring Lparameters plstr Local mlenstr diff --git a/TODOS.md b/TODOS.md index 645caa1..068fb72 100644 --- a/TODOS.md +++ b/TODOS.md @@ -225,3 +225,17 @@ Sursa: `docs/diff-TRANSA-cache-anaf.md`, `docs/handoff_cache_anaf.md`. - **De ce nu acum:** fara efect (motorul `PACK_UPDATE` dispecerizeaza dupa numele fisierului de pe disc, nu dupa stringul din `versiune`) — curatenie de mediu de test, nu de productie. - **Efort:** S. **Depinde de:** nimic, se poate face oricand. + +## Amanari review /autoplan — import extrase (13.09.2026) + +## P2 — Acceptare in bloc a randurilor sigure la importul de extrase +- **Ce:** in `frm_modific2024`, "accepta toate verzile": randurile cu partener din CUI/IBAN exact si factura cu nr. in text + sold exact se confirma dintr-un clic, cu urma de audit; operatorul lucreaza doar exceptiile. +- **De ce:** 300 de randuri/luna verificate unul cate unul; minutele pe extras sunt metrica reala, nu procentul de potrivire. +- **Contra:** contrazice premisa confirmata "verificare rand cu rand"; cere intai precizie masurata out-of-sample. +- **Context:** `docs/plan_import_extrase_review.md` C6. **Efort:** M → S. **Depinde de:** Nivel 1 + Nivel 2 livrate, backtest. + +## P3 — Flux bancar PSD2 in locul fisierului lunar +- **Ce:** test cu un agregator licentiat (AISP) pentru BT/BCR care alimenteaza acelasi motor de identificare. +- **De ce:** SmartBill/Oblio aduc deja tranzactiile automat; "import fisier lunar" imbatraneste in 12-24 luni. +- **Contra:** contract cu agregator, consimtamant per client, cost recurent. +- **Context:** review C7; motorul din Nivel 1 se scrie independent de sursa. **Efort:** L → M. **Depinde de:** decizie comerciala. diff --git a/changelog_roacont.txt b/changelog_roacont.txt index a7f75ca..dba8861 100644 --- a/changelog_roacont.txt +++ b/changelog_roacont.txt @@ -1,3 +1,19 @@ + +