From 92dc8c7b32e1b4c9eb59628ef0f7c08e0fd46039 Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Mon, 21 Sep 2026 00:02:30 +0300 Subject: [PATCH] solduri2roa: balante SAGA PDF -> xlsx initializare ROACONT Extragere pe coordonate (pdfplumber), generarea celor doua xlsx pentru FUNDATIA si MASTER 12/2025, regulile de mapare si rapoartele de verificare. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01BdA5a3ECKFD6Citf1ptPZu --- .gitignore | 2 + CLAUDE.md | 33 +++ IBB 31.12.2025.pdf | Bin 0 -> 31408 bytes MJC 31.12.2025.pdf | Bin 0 -> 31085 bytes balanta_FUNDATIA.csv | 89 ++++++ balanta_MASTERJOB.csv | 89 ++++++ docs/config_cont_ireg.md | 91 ++++++ docs/conturi_cu_analitice.md | 166 +++++++++++ docs/decizii_import.md | 116 ++++++++ docs/plan_solduri2roa.md | 58 ++++ docs/prompt_initial.md | 12 + docs/raport_config-cont-ireg.md | 25 ++ docs/raport_form_init_balanta.md | 217 ++++++++++++++ docs/raport_genxlsx.md | 65 ++++ docs/raport_pdf_extract.md | 57 ++++ docs/verificare_FUNDATIA.md | 60 ++++ docs/verificare_MASTER.md | 63 ++++ extract_balanta.py | 243 +++++++++++++++ genereaza_xlsx.py | 490 +++++++++++++++++++++++++++++++ init_FUNDATIA_2025_12.xlsx | Bin 0 -> 11192 bytes init_MASTER_2025_12.xlsx | Bin 0 -> 11299 bytes init_facturi_balanta_note.xlsx | Bin 0 -> 18102 bytes 22 files changed, 1876 insertions(+) create mode 100644 .gitignore create mode 100644 CLAUDE.md create mode 100644 IBB 31.12.2025.pdf create mode 100644 MJC 31.12.2025.pdf create mode 100644 balanta_FUNDATIA.csv create mode 100644 balanta_MASTERJOB.csv create mode 100644 docs/config_cont_ireg.md create mode 100644 docs/conturi_cu_analitice.md create mode 100644 docs/decizii_import.md create mode 100644 docs/plan_solduri2roa.md create mode 100644 docs/prompt_initial.md create mode 100644 docs/raport_config-cont-ireg.md create mode 100644 docs/raport_form_init_balanta.md create mode 100644 docs/raport_genxlsx.md create mode 100644 docs/raport_pdf_extract.md create mode 100644 docs/verificare_FUNDATIA.md create mode 100644 docs/verificare_MASTER.md create mode 100644 extract_balanta.py create mode 100644 genereaza_xlsx.py create mode 100644 init_FUNDATIA_2025_12.xlsx create mode 100644 init_MASTER_2025_12.xlsx create mode 100644 init_facturi_balanta_note.xlsx diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a60b85 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.pyc diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..268174e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,33 @@ +# solduri2roa + +Convertor balante SAGA (PDF) -> xlsx de initializare solduri ROACONT. + +## Mediu +- `py` (Python 3.13). Instalate: pdfplumber, openpyxl. Fara alte dependinte. +- Nu folosi `sed -i` (corupe fisierele). Scrie cu heredoc sau Python. +- `D:\ROA\ROACONT` = read-only. Nu comite (git/svn) fara aprobare. + +## Fisiere +| | | +|---|---| +| `extract_balanta.py` | PDF -> `balanta_.csv` (pdfplumber pe coordonate) | +| `genereaza_xlsx.py` | CSV -> `init___.xlsx` | +| `init_facturi_balanta_note.xlsx` | sablonul ROA (rand 1 = coloane, 2-13 instructiuni, 20+ exemple) | +| `docs/decizii_import.md` | **regulile de mapare - citeste intai** | +| `docs/conturi_cu_analitice.md` | per cont: ANALITIC sau PARTENER (confirmat de Marius) | +| `docs/config_cont_ireg.md` | `CONFIG_CONT_IREG` din Oracle local; `CONT` e VARCHAR2(4) | +| `docs/raport_form_init_balanta.md` | semantica formularului de import ROACONT | +| `docs/plan_solduri2roa.md` | etapele | + +## Reguli care se uita usor +- `pdftotext` decaleaza coloanele. Doar pdfplumber, grupare pe `top`, coloane dupa `x1`. +- `totdeb`/`totcred` = **sume totale**, nu solduri (bilantul/CPP se bazeaza pe ele). +- In xlsx intra **doar frunzele**; importul reface sinteticul din suma analiticelor. +- Conturile cu parteneri nu primesc analitice: rand `BALANTA` pe sintetic + cate un `FACTURA` per partener. +- `cont` <= 4 car., `acont` <= 4 car. Analitic SAGA lung -> cifre concatenate (`1171.01.12` -> `0112`). +- SAGA neteaza D/C la sintetice: diferentele se calculeaza **pe net**. Net != 0 -> analitic/partener de diferenta. +- Nu ajusta cifre ca sa treaca o verificare. Raporteaza. + +## Verificari obligatorii inainte de a declara gata +`SUM(totdeb)=SUM(totcred)`; total = randul "Totaluri:" din PDF; fiecare frunza din CSV apare exact o data; +per cont cu parteneri `SUM(sold FACTURA)` = netul sinteticului; fara `(cont,acont)` duplicat. diff --git a/IBB 31.12.2025.pdf b/IBB 31.12.2025.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1abea7e9ac0205c07b9202f611e2cf54a54c22b3 GIT binary patch literal 31408 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 literal 0 HcmV?d00001 diff --git a/MJC 31.12.2025.pdf b/MJC 31.12.2025.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0dbee2c0392e8f9f28ddd5d158886453b83ac4cd GIT binary patch literal 31085 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%0A9c3S?EK!}wc@Gr(!Q{HZY8}-}1=1%=?uBtDJ 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

Qdt+(w^@gz^8t= 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 GyZtX_SmW*h literal 0 HcmV?d00001 diff --git a/balanta_FUNDATIA.csv b/balanta_FUNDATIA.csv new file mode 100644 index 0000000..160337a --- /dev/null +++ b/balanta_FUNDATIA.csv @@ -0,0 +1,89 @@ +pagina,cont,denumire,prec_d,prec_c,rulaj_d,rulaj_c,total_d,total_c,sold_d,sold_c,este_total +1,101,CAPITAL SOCIAL,0.0,15000.0,0.0,0.0,0.0,15000.0,0.0,15000.0,0 +1,1171,REZULTATUL REPORTAT - PROFITUL NEREP./ PIREDERE NEACOP.,629448.54,0.0,144159.56,0.0,773608.1,0.0,773608.1,0.0,0 +1,1171.01,REZ. REPORTAT PT. EXCEDENT NEREP. SAU DEFICIT NEACOP. - AFSP,629448.54,0.0,144159.56,0.0,773608.1,0.0,773608.1,0.0,0 +1,1171.01.01,REZULTAT REPORTAT - 2013,7245.69,0.0,0.0,0.0,7245.69,0.0,7245.69,0.0,0 +1,1171.01.02,REZULTAT REPORTAT- 2014,0.0,462166.48,0.0,0.0,0.0,462166.48,0.0,462166.48,0 +1,1171.01.03,REZULTAT REPORTAT- 2015,62733.0,0.0,0.0,0.0,62733.0,0.0,62733.0,0.0,0 +1,1171.01.04,REZULTAT REPORTAT 2016,463593.57,0.0,0.0,0.0,463593.57,0.0,463593.57,0.0,0 +1,1171.01.05,REZULTAT REPORTAT 2017,64580.26,0.0,0.0,0.0,64580.26,0.0,64580.26,0.0,0 +1,1171.01.06,REZULTAT REPORTAT 2018,53819.82,0.0,0.0,0.0,53819.82,0.0,53819.82,0.0,0 +1,1171.01.07,REPORTAT PROFIT/PIERDERE 2019,0.0,277665.19,0.0,0.0,0.0,277665.19,0.0,277665.19,0 +1,1171.01.08,REPORTAT PROFIT/PIERDERE 2020,35546.5,0.0,0.0,0.0,35546.5,0.0,35546.5,0.0,0 +1,1171.01.09,REPORTAT PROFIT/PIERDERE 2021,67800.91,0.0,0.0,0.0,67800.91,0.0,67800.91,0.0,0 +1,1171.01.10,REPORTAT PROFIT/PIERDERE 2022,106630.74,0.0,0.0,0.0,106630.74,0.0,106630.74,0.0,0 +1,1171.01.11,REPORTAT PROFIT/PIERDERE 2023,507329.72,0.0,0.0,0.0,507329.72,0.0,507329.72,0.0,0 +1,1171.01.12,REPORTAT PROFIT/PIERDERE 2024,0.0,0.0,144159.56,0.0,144159.56,0.0,144159.56,0.0,0 +1,1211,EXCEDENT SAU DEFICIT PRIVIND AFSP,164431.54,0.0,130661.51,144159.56,295093.05,144159.56,150933.49,0.0,0 +1,1211.01,EXCEDENT SAU DEFICIT PRIVIND AFSP,164431.54,0.0,130661.51,144159.56,295093.05,144159.56,150933.49,0.0,0 +1,,Total sume clasa 1,793880.08,15000.0,274821.07,144159.56,1068701.15,159159.56,924541.59,15000.0,1 +1,2111,TERENURI,100000.0,0.0,0.0,0.0,100000.0,0.0,100000.0,0.0,0 +1,2111.03,TEREN MOGOSOAIA -260MP /NR CADASTRU 61309,100000.0,0.0,0.0,0.0,100000.0,0.0,100000.0,0.0,0 +1,212,CONSTRUCTII,1408257.53,0.0,0.0,0.0,1408257.53,0.0,1408257.53,0.0,0 +1,212.01,IMOBIL TEREN + CLADIRE MOGOSOAIA,241612.68,0.0,0.0,0.0,241612.68,0.0,241612.68,0.0,0 +1,212.02,IMOBIL APARTAMENT GH. BARITIU,244085.95,0.0,0.0,0.0,244085.95,0.0,244085.95,0.0,0 +1,212.03,IMOBIL MIERCANI TEREN + CONSTRUCTIE,331042.5,0.0,0.0,0.0,331042.5,0.0,331042.5,0.0,0 +1,212.04,IMOBIL STR COCARESCU NR 22,392986.4,0.0,0.0,0.0,392986.4,0.0,392986.4,0.0,0 +1,212.05,IMOBIL MOGOSOAIA-NR CADASTRU 61309,198530.0,0.0,0.0,0.0,198530.0,0.0,198530.0,0.0,0 +1,213,"INSTALATII TEHNICE,MIJ. TRANSP., ANIMALE SI PLANTATII",6300.0,0.0,0.0,0.0,6300.0,0.0,6300.0,0.0,0 +1,2133,MIJLOACE DE TRANSPORT C,250985.0,0.0,0.0,0.0,250985.0,0.0,250985.0,0.0,0 +2,214,"MOBILIER,APARATURA BIROTICA,ETC.",30950.0,0.0,0.0,0.0,30950.0,0.0,30950.0,0.0,0 +2,2812,AMORT. CONSTRUCTIILOR,0.0,409032.32,0.0,55016.88,0.0,464049.2,0.0,464049.2,0 +2,2813,"AMORT. INST., MIJ. DE TRANSPORT",0.0,177781.03,0.0,62746.26,0.0,240527.29,0.0,240527.29,0 +2,2814,AMORT. ALTOR IMOBILIZARI CORP.,0.0,16764.62,0.0,3868.74,0.0,20633.36,0.0,20633.36,0 +2,2814.01,"AMORT. AP. SI INST. DE MASURARE, CONTROL SI REGLARE - AFSP",0.0,16764.62,0.0,3868.74,0.0,20633.36,0.0,20633.36,0 +2,,Total sume clasa 2,1796492.53,603577.97,0.0,121631.88,1796492.53,725209.85,1796492.53,725209.85,1 +2,401,FURNIZORI,0.0,305673.95,0.0,9029.63,0.0,314703.58,0.0,314703.58,0 +2,401.00004,GTC AUTO TRADE,0.0,0.3,0.0,0.0,0.0,0.3,0.0,0.3,0 +2,401.00018,HOSTVISION SRL,0.0,143.92,0.0,470.18,0.0,614.1,0.0,614.1,0 +2,401.00043,BRIT MOTOR AG SRL,0.0,374.85,0.0,6265.77,0.0,6640.62,0.0,6640.62,0 +2,401.00045,TRACOM IMPEX S.R.L.,0.0,0.0,0.0,1392.75,0.0,1392.75,0.0,1392.75,0 +2,401.00049,APA CANAL ILFOV,0.0,604.89,0.0,521.93,0.0,1126.82,0.0,1126.82,0 +2,401.00050,SC CEGIM SRL,0.0,5599.99,0.0,0.0,0.0,5599.99,0.0,5599.99,0 +2,401.00051,S.C. CRAMA SPARLENI SRL,0.0,420.0,0.0,0.0,0.0,420.0,0.0,420.0,0 +2,401.00053,POPESCU LUMINITA-MACOVICIUC VERONICA,0.0,298530.0,0.0,0.0,0.0,298530.0,0.0,298530.0,0 +2,401.00054,DEDEMAN SRL,0.0,0.0,0.0,190.0,0.0,190.0,0.0,190.0,0 +2,401.00055,AGROMECANIC IMPEX SRL,0.0,0.0,0.0,189.0,0.0,189.0,0.0,189.0,0 +2,409,FURNIZORI DEBITORI,-0.01,0.0,0.0,0.0,-0.01,0.0,-0.01,0.0,0 +2,4092,FUR.-DEBIT PT.PRESTARI SERVICII,809.33,0.0,0.0,0.0,809.33,0.0,809.33,0.0,0 +2,4092.1,HOSTVISION,547.65,0.0,0.0,0.0,547.65,0.0,547.65,0.0,0 +2,4092.2,ROMARG,217.7,0.0,0.0,0.0,217.7,0.0,217.7,0.0,0 +2,4092.3,HORVARTH ALINA GABRIELA PROMISIUNE VZ-C,43.98,0.0,0.0,0.0,43.98,0.0,43.98,0.0,0 +2,4111,CLIENTI,15126.48,0.0,0.0,0.0,15126.48,0.0,15126.48,0.0,0 +2,4111.00004,EM INTERNATIONAL SERVICES GROUP S.R.L.,15126.48,0.0,0.0,0.0,15126.48,0.0,15126.48,0.0,0 +2,4411,IMPOZITUL PE PROFIT,0.0,26986.0,0.0,0.0,0.0,26986.0,0.0,26986.0,0 +2,446,ALTE IMPOZITE SI TAXE,0.0,-485.0,0.0,0.0,0.0,-485.0,0.0,-485.0,0 +2,446.1,IMPOZIT TEREN,0.0,-485.0,0.0,0.0,0.0,-485.0,0.0,-485.0,0 +2,4482,ALTE CREANTE FATA DE BUGET,17264.38,0.0,0.0,0.0,17264.38,0.0,17264.38,0.0,0 +2,4551,ASOCIATI-CONTURI CURENTE,0.0,1571531.33,0.0,0.0,0.0,1571531.33,0.0,1571531.33,0 +2,4551.01,IONESCU VALENTIN GHEORGHE,0.0,1383131.33,0.0,0.0,0.0,1383131.33,0.0,1383131.33,0 +2,4551.02,EURO ANTR RO12 PIRB 4250 7735 C 0200 1000,0.0,188400.0,0.0,0.0,0.0,188400.0,0.0,188400.0,0 +3,461,DEBITORI DIVERSI,477938.37,0.0,0.0,0.0,477938.37,0.0,477938.37,0.0,0 +3,461.01,SISTEME INTERNATIONALE DE AFACERI,15031.49,0.0,0.0,0.0,15031.49,0.0,15031.49,0.0,0 +3,461.02,IMPRUMUT ASOC. NO-ADD,10800.0,0.0,0.0,0.0,10800.0,0.0,10800.0,0.0,0 +3,461.03,TEMPLUM,29445.23,0.0,0.0,0.0,29445.23,0.0,29445.23,0.0,0 +3,461.04,DEBITOR EURO ANTREPRENOR,417000.01,0.0,0.0,0.0,417000.01,0.0,417000.01,0.0,0 +3,461.06,ADRIAN CRISTESCU,5000.0,0.0,0.0,0.0,5000.0,0.0,5000.0,0.0,0 +3,461.07,FUNDATIA DOMENIU OTETELESANU,661.64,0.0,0.0,0.0,661.64,0.0,661.64,0.0,0 +3,462,CREDITORI DIVERSI,0.0,3400771.0,0.0,0.0,0.0,3400771.0,0.0,3400771.0,0 +3,462.01,TEMPLUM PLUS,0.0,988640.0,0.0,0.0,0.0,988640.0,0.0,988640.0,0 +3,462.04,CREDITOR EURO PRO CONSTRUCT,0.0,1869897.0,0.0,0.0,0.0,1869897.0,0.0,1869897.0,0 +3,462.05,MODREA ALAIN FLORIN,0.0,542234.0,0.0,0.0,0.0,542234.0,0.0,542234.0,0 +3,473,DEC. DIN OP. IN CURS DE CLARIF.,14094.02,0.0,0.0,0.0,14094.02,0.0,14094.02,0.0,0 +3,,Total sume clasa 4,525232.57,5304477.28,0.0,9029.63,525232.57,5313506.91,525232.57,5313506.91,1 +3,5121,CONTURI LA BANCA IN LEI,81966.8,0.0,0.0,0.0,81966.8,0.0,81966.8,0.0,0 +3,5121.01,RO73 BACX 0000 0008 7243 0001,81966.8,0.0,0.0,0.0,81966.8,0.0,81966.8,0.0,0 +3,5124,CONTURI LA BANCA IN DEVIZE,2492540.28,0.0,0.0,0.0,2492540.28,0.0,2492540.28,0.0,0 +3,5124.01,RO89 BACX 0000 0008 7243 0004 - EURO,2492540.28,0.0,0.0,0.0,2492540.28,0.0,2492540.28,0.0,0 +3,5125,SUME IN CURS DE DECONTARE,160509.43,0.0,0.0,0.0,160509.43,0.0,160509.43,0.0,0 +3,5125.03,SUME PROPRIRI ANAF,1490.02,0.0,0.0,0.0,1490.02,0.0,1490.02,0.0,0 +3,5125.04,SUME IN CURS DECONTARE,159019.41,0.0,0.0,0.0,159019.41,0.0,159019.41,0.0,0 +3,5311,CASA IN LEI,72433.56,0.0,0.0,0.0,72433.56,0.0,72433.56,0.0,0 +3,,Total sume clasa 5,2807450.07,0.0,0.0,0.0,2807450.07,0.0,2807450.07,0.0,1 +3,6024,CHELT. CU PIESELE DE SCHIMB,0.0,0.0,1392.75,1392.75,1392.75,1392.75,0.0,0.0,0 +3,6051,CHELT. PRIVIND CONSUMUL DE ENERGIE,0.0,0.0,521.93,521.93,521.93,521.93,0.0,0.0,0 +3,611,CHELT. CU INTRETINEREA SI REP.,0.0,0.0,6265.77,6265.77,6265.77,6265.77,0.0,0.0,0 +3,628,ALTE CHELT.CU SERV.LA TERTI,0.0,0.0,849.18,849.18,849.18,849.18,0.0,0.0,0 +3,6811,CHELT. DE EXPL.CU AMORT. IMOB.,0.0,0.0,121631.88,121631.88,121631.88,121631.88,0.0,0.0,0 +3,,Total sume clasa 6,0.0,0.0,130661.51,130661.51,130661.51,130661.51,0.0,0.0,1 +4,,Totaluri:,5923055.25,5923055.25,405482.58,405482.58,6328537.83,6328537.83,6053716.76,6053716.76,1 diff --git a/balanta_MASTERJOB.csv b/balanta_MASTERJOB.csv new file mode 100644 index 0000000..170a50f --- /dev/null +++ b/balanta_MASTERJOB.csv @@ -0,0 +1,89 @@ +pagina,cont,denumire,prec_d,prec_c,rulaj_d,rulaj_c,total_d,total_c,sold_d,sold_c,este_total +1,1012,CAPITAL SUBSCRIS VARSAT,0.0,90000.0,0.0,0.0,0.0,90000.0,0.0,90000.0,0 +1,117,REZULTATUL REPORTAT,47431.79,0.0,0.0,0.0,47431.79,0.0,47431.79,0.0,0 +1,117.1,PIERDERE REPORTATA,4280.23,0.0,0.0,0.0,4280.23,0.0,4280.23,0.0,0 +1,117.2,PIERDERE REPORTATA,7743.14,0.0,0.0,0.0,7743.14,0.0,7743.14,0.0,0 +1,117.3,PIERDERE REPORTATA,7037.7,0.0,0.0,0.0,7037.7,0.0,7037.7,0.0,0 +1,117.4,PIERDERE 2007,7531.03,0.0,0.0,0.0,7531.03,0.0,7531.03,0.0,0 +1,117.5,PIERDERE 2008,5731.08,0.0,0.0,0.0,5731.08,0.0,5731.08,0.0,0 +1,117.6,PIERDERE 2009,3421.65,0.0,0.0,0.0,3421.65,0.0,3421.65,0.0,0 +1,117.7,PIERDERE 2010,2764.43,0.0,0.0,0.0,2764.43,0.0,2764.43,0.0,0 +1,117.8,PIERDERE 2011,6286.66,0.0,0.0,0.0,6286.66,0.0,6286.66,0.0,0 +1,1171,REZULTATUL REPORTAT - PROFITUL NEREP./ PIREDERE NEACOP.,106880.87,0.0,103625.3,0.0,210506.17,0.0,210506.17,0.0,0 +1,121,PROFIT SI PIERDERE,103625.3,0.0,100135.51,103625.3,203760.81,103625.3,100135.51,0.0,0 +1,,Total sume clasa 1,257937.96,90000.0,203760.81,103625.3,461698.77,193625.3,358073.47,90000.0,1 +1,201,CHELTUIELI DE CONSTITUIRE,581.27,0.0,0.0,0.0,581.27,0.0,581.27,0.0,0 +1,2111,TERENURI,439966.6,0.0,0.0,0.0,439966.6,0.0,439966.6,0.0,0 +1,2111.01,RISNOV- BRASOV,439966.6,0.0,0.0,0.0,439966.6,0.0,439966.6,0.0,0 +1,235,INVESTITII IMOBILIARE IN CURS DE EXECUTIE,292.0,0.0,0.0,0.0,292.0,0.0,292.0,0.0,0 +1,2813,"AMORT. INSTALATIILOR, MIJ. DE TRANSPORT",0.0,249314.46,0.0,87993.3,0.0,337307.76,0.0,337307.76,0 +1,,Total sume clasa 2,440839.87,249314.46,0.0,87993.3,440839.87,337307.76,440839.87,337307.76,1 +1,303,MAT. DE NATURA OB. DE INVENTAR,16802.46,0.0,0.0,0.0,16802.46,0.0,16802.46,0.0,0 +1,371,MARFURI,38850.0,0.0,0.0,0.0,38850.0,0.0,38850.0,0.0,0 +1,371.01,FURAJE PASTRAV,38850.0,0.0,0.0,0.0,38850.0,0.0,38850.0,0.0,0 +1,,Total sume clasa 3,55652.46,0.0,0.0,0.0,55652.46,0.0,55652.46,0.0,1 +1,401,FURNIZORI,0.0,534966.78,0.0,12142.21,0.0,547108.99,0.0,547108.99,0 +1,401.00001,MEDIAROM COMUNICATIONS,0.0,14293.76,0.0,0.0,0.0,14293.76,0.0,14293.76,0 +1,401.00003,TEMPLUM PLUS,0.0,500.0,0.0,0.0,0.0,500.0,0.0,500.0,0 +1,401.00006,BIROU INDIVIDUAL NOTARIAL GEORGE TRAGONE,0.0,952.0,0.0,0.0,0.0,952.0,0.0,952.0,0 +1,401.00007,ACVATIC TES S.R.L.,0.0,439966.6,0.0,0.0,0.0,439966.6,0.0,439966.6,0 +1,401.00008,DREAM FISH S.R.L.,0.0,38850.0,0.0,0.0,0.0,38850.0,0.0,38850.0,0 +1,401.00009,LEROY MERLIN ROMANIA SRL C,0.0,2902.91,0.0,0.0,0.0,2902.91,0.0,2902.91,0 +2,401.00010,SERVICE ONLAPTOP S.R.L.,0.0,1230.0,0.0,0.0,0.0,1230.0,0.0,1230.0,0 +2,401.00011,PET PRODUCT SRL,0.0,445.05,0.0,0.0,0.0,445.05,0.0,445.05,0 +2,401.00012,BIROU INDIVIDUAL NOTARIAL PIELEANU DANIELA,0.0,4879.0,0.0,0.0,0.0,4879.0,0.0,4879.0,0 +2,401.00013,CREATIV EXPERT CONSTRUCT S.R.L.,0.0,3300.0,0.0,0.0,0.0,3300.0,0.0,3300.0,0 +2,401.00014,,0.0,16802.46,0.0,0.0,0.0,16802.46,0.0,16802.46,0 +2,401.00015,ANDREEA BEATRICE VASILE,0.0,10000.0,0.0,0.0,0.0,10000.0,0.0,10000.0,0 +2,401.00017,TIRES AND PARTS SRL,0.0,845.0,0.0,400.0,0.0,1245.0,0.0,1245.0,0 +2,401.00023,ANGLO CARS S.R.L.,0.0,0.0,0.0,3700.9,0.0,3700.9,0.0,3700.9,0 +2,401.00024,DAW BENTA SRL,0.0,0.0,0.0,1948.01,0.0,1948.01,0.0,1948.01,0 +2,401.00025,ROMSYSTEMS S.R.L.,0.0,0.0,0.0,1380.4,0.0,1380.4,0.0,1380.4,0 +2,401.00026,UNIVERSAL GRUP SRL,0.0,0.0,0.0,1380.9,0.0,1380.9,0.0,1380.9,0 +2,401.00027,SEBASTIAN CONSTRUCTII MONTAJ SRL,0.0,0.0,0.0,3332.0,0.0,3332.0,0.0,3332.0,0 +2,4092,FURNIZORI — DEBITORI PT. PRESTARI DE SERVICII,4.0,0.0,0.0,0.0,4.0,0.0,4.0,0.0,0 +2,4092.01,ICI,4.0,0.0,0.0,0.0,4.0,0.0,4.0,0.0,0 +2,4111,CLIENTI,12000.0,0.0,0.0,0.0,12000.0,0.0,12000.0,0.0,0 +2,4111.00001,NEW HOME CONSTRUCT S.A.,12000.0,0.0,0.0,0.0,12000.0,0.0,12000.0,0.0,0 +2,421,PERSONAL - SALARII DATORATE,0.0,17689.0,0.0,0.0,0.0,17689.0,0.0,17689.0,0 +2,4315,CONTR. DE ASIGURARI SOCIALE,0.0,24297.0,0.0,0.0,0.0,24297.0,0.0,24297.0,0 +2,4316,CONTR. DE ASIGURARI SOCIALE DE SANATATE,0.0,10905.0,0.0,0.0,0.0,10905.0,0.0,10905.0,0 +2,436,CONTR. ASIGURATORIE DE MUNCA,0.0,1128.0,0.0,0.0,0.0,1128.0,0.0,1128.0,0 +2,4372,CONTRIBUTIA PERSONALULUI LA FONDUL DE SOMAJ,0.0,52.0,0.0,0.0,0.0,52.0,0.0,52.0,0 +2,441,IMPOZITUL PE PROFIT SI ALTE IMPOZITE,0.0,2567.0,0.0,0.0,0.0,2567.0,0.0,2567.0,0 +2,441.01,IMPOZIT FORFETAR,0.0,2567.0,0.0,0.0,0.0,2567.0,0.0,2567.0,0 +2,4411,IMPOZITUL PE PROFIT,0.0,7804.0,0.0,0.0,0.0,7804.0,0.0,7804.0,0 +2,4418,IMPOZITUL PE VENIT,0.0,360.0,0.0,0.0,0.0,360.0,0.0,360.0,0 +2,4424,TVA DE RECUPERAT,4669.56,0.0,0.0,0.0,4669.56,0.0,4669.56,0.0,0 +2,444,IMPOZITUL PE VENITURI DE NATURA SALARIILOR,0.0,3105.0,0.0,0.0,0.0,3105.0,0.0,3105.0,0 +2,447,FONDURI SPECIALE TAXE SI VARSAMINTE ASIMILATE,0.0,47.0,0.0,0.0,0.0,47.0,0.0,47.0,0 +2,447.01,COMISION ITM C,0.0,47.0,0.0,0.0,0.0,47.0,0.0,47.0,0 +3,4551,ACTIONARI/ASOCIATI - CONTURI CURENTE,0.0,751724.61,0.0,0.0,0.0,751724.61,0.0,751724.61,0 +3,4551.01,IONESCU VALENTIN,0.0,729308.61,0.0,0.0,0.0,729308.61,0.0,729308.61,0 +3,4551.02,TOMA IONEL VIOREL RO55 RZBR 0000 0600 1338 1717,0.0,22416.0,0.0,0.0,0.0,22416.0,0.0,22416.0,0 +3,461,DEBITORI DIVERSI,69289.0,0.0,0.0,0.0,69289.0,0.0,69289.0,0.0,0 +3,461.01,SISTEME INTARNATIONALE DE AF.,8289.0,0.0,0.0,0.0,8289.0,0.0,8289.0,0.0,0 +3,461.02,HABITAT SI AMBIENT,20000.0,0.0,0.0,0.0,20000.0,0.0,20000.0,0.0,0 +3,461.03,DEBITORI DIVERSI,41000.0,0.0,0.0,0.0,41000.0,0.0,41000.0,0.0,0 +3,462,CREDITORI DIVERSI,0.0,9810.0,0.0,0.0,0.0,9810.0,0.0,9810.0,0 +3,462.01,CREDITORI DIVERSI -IONESCU ALINA,0.0,3350.0,0.0,0.0,0.0,3350.0,0.0,3350.0,0 +3,462.02,CREDITORI DIVERSI - REZIDENT COM,0.0,700.0,0.0,0.0,0.0,700.0,0.0,700.0,0 +3,462.03,CREDITORI DIVERSI - IONESCU VALENTIN,0.0,760.0,0.0,0.0,0.0,760.0,0.0,760.0,0 +3,462.05,CREDITOR C.S.C.,0.0,5000.0,0.0,0.0,0.0,5000.0,0.0,5000.0,0 +3,473,DECONTARI DIN OPERATIUNI IN CURS DE CLARIFICARE,0.0,310905.94,0.0,0.0,0.0,310905.94,0.0,310905.94,0 +3,,Total sume clasa 4,85962.56,1675361.33,0.0,12142.21,85962.56,1687503.54,85962.56,1687503.54,1 +3,5121,CONTURI LA BANCA IN LEI,15730.61,0.0,0.0,0.0,15730.61,0.0,15730.61,0.0,0 +3,5121.01,PIRAEUS BANK - RON,0.0,20.8,0.0,0.0,0.0,20.8,0.0,20.8,0 +3,5121.02,RO45 PIRB 4250 7073 2600 1000 FIRST BANK,15599.25,0.0,0.0,0.0,15599.25,0.0,15599.25,0.0,0 +3,5124,CONTURI LA BANCA IN VALUTA,1060090.96,0.0,0.0,0.0,1060090.96,0.0,1060090.96,0.0,0 +3,5124.01,BANCA (EURO),5.71,0.0,0.0,0.0,5.71,0.0,5.71,0.0,0 +3,5124.02,RO11 PIRB 4250 7073 2600 2000 FIRST,1060085.25,0.0,0.0,0.0,1060085.25,0.0,1060085.25,0.0,0 +3,5125,SUME IN CURS DE DECONTARE,0.5,0.0,0.0,0.0,0.5,0.0,0.5,0.0,0 +3,5125.03,POPRIRE,0.5,0.0,0.0,0.0,0.5,0.0,0.5,0.0,0 +3,5311,CASA IN LEI,98460.87,0.0,0.0,0.0,98460.87,0.0,98460.87,0.0,0 +3,,Total sume clasa 5,1174282.94,0.0,0.0,0.0,1174282.94,0.0,1174282.94,0.0,1 +3,611,CHELT. CU INTRETINEREA SI REPARATIILE,0.0,0.0,2510.9,2510.9,2510.9,2510.9,0.0,0.0,0 +3,628,ALTE CHELT. CU SERVICIILE EXECUTATE DE TERTI,0.0,0.0,9631.31,9631.31,9631.31,9631.31,0.0,0.0,0 +3,6811,CHELT. DE EXPLOATARE CU AMORTIZAREA IMOBILIZARILOR,0.0,0.0,87993.3,87993.3,87993.3,87993.3,0.0,0.0,0 +3,,Total sume clasa 6,0.0,0.0,100135.51,100135.51,100135.51,100135.51,0.0,0.0,1 +4,,Totaluri:,2014675.79,2014675.79,303896.32,303896.32,2318572.11,2318572.11,2114811.3,2114811.3,1 diff --git a/docs/config_cont_ireg.md b/docs/config_cont_ireg.md new file mode 100644 index 0000000..a058a66 --- /dev/null +++ b/docs/config_cont_ireg.md @@ -0,0 +1,91 @@ +# CONFIG_CONT_IREG (MARIUSM_AUTO@ROA_CENTRAL) + +Sursa: Oracle LOCAL (server dezvoltare ROA_CENTRAL), NU productie. + +## Sursa si conectare + +- DSN (tnsnames.ora, `D:\ROA\instantclient_19_18\tnsnames.ora:206`): `ROA_CENTRAL` = HOST 10.0.20.121, PORT 1521, SERVICE_NAME ROA +- Schema citita: `MARIUSM_AUTO` +- Comanda exacta folosita: + +``` +set TNS_ADMIN=D:\ROA\instantclient_19_18 +set NLS_LANG=ROMANIAN_ROMANIA.AL32UTF8 +sqlplus.exe -S "MARIUSM_AUTO/ROMFASTSOFT@ROA_CENTRAL" +``` + +Parola: din `D:\ROA\ROACONT\docs\oracle_parola_standard.secret` (valoare implicita si in `COMUN\utile\Teste\test_init_env_auto.prg:22`). + +## Structura tabelei (DESC) + +| Coloana | Tip | NULL? | +|---|---|---| +| ID_CONT_IREG | NUMBER | N | +| CONT | VARCHAR2(4) | Y | +| EXPLICATIE | VARCHAR2(50) | Y | +| FEL_CONT | NUMBER | Y | +| CU_INREGISTRARI | NUMBER | Y | +| CU_VENCHELT | NUMBER | N | +| CU_PROC_TVA | NUMBER | N | +| LUNAI | NUMBER | Y | +| ANI | NUMBER | Y | + +Observatie: coloana ceruta ca "denumire" este de fapt `EXPLICATIE`. Tabela are si coloanele `FEL_CONT`, `CU_VENCHELT`, `CU_PROC_TVA`, `LUNAI`, `ANI`. `LUNAI`/`ANI` sunt completate doar pe randul 4511. + +## Randuri (47) + +| ID_CONT_IREG | CONT | EXPLICATIE | FEL_CONT | CU_INREGISTRARI | CU_VENCHELT | CU_PROC_TVA | LUNAI | ANI | +|---|---|---|---|---|---|---|---|---| +| 63 | 1011 | 1011 | 1 | 0 | 0 | 0 | | | +| 59 | 1621 | CREDITE PE TERMEN LUNG | 1 | 1 | 0 | 0 | | | +| 54 | 167 | 167 | 1 | 1 | 0 | 0 | | | +| 61 | 232 | AVANSURI FZ IMOB CORPORALE | 0 | 1 | 0 | 0 | | | +| 62 | 234 | AVANSURI FZ IMOB NECORPORALE | 0 | 1 | 0 | 0 | | | +| 47 | 261 | TITLURI DE PARTICIPARELA FILIALE DIN GRUP | 0 | 1 | 0 | 0 | | | +| 48 | 2678 | CREANTE IMOBILIZATE | 0 | 1 | 0 | 0 | | | +| 53 | 2691 | VARS.REF.TIT.PART.DET.LA FIL.GRUP | 1 | 1 | 0 | 0 | | | +| 60 | 371 | MARFA | 0 | 0 | 0 | 0 | | | +| 1 | 401 | FURNIZORI | 1 | 1 | 0 | 0 | | | +| 73 | 403 | EF. COM. 403 | 1 | 1 | 0 | 0 | | | +| 2 | 404 | FURNIZORI IMOBILIZARI | 1 | 1 | 0 | 0 | | | +| 3 | 408 | FACTURI NESOSITE | 1 | 1 | 0 | 1 | | | +| 4 | 409 | AVANSURI FURNIZORI | 0 | 1 | 0 | 0 | | | +| 56 | 4091 | AVANSURI FURNIZORI | 0 | 1 | 0 | 0 | | | +| 57 | 4092 | AVANSURI FURNIZORI | 0 | 1 | 0 | 0 | | | +| 79 | 4093 | AVANSURI FURNIZORI | 0 | 1 | 0 | 0 | | | +| 80 | 4094 | AVANSURI FURNIZORI | 0 | 1 | 0 | 0 | | | +| 5 | 4111 | CLIENTI | 0 | 1 | 0 | 0 | | | +| 6 | 4118 | CLIENTI INCERTI | 0 | 1 | 0 | 0 | | | +| 72 | 413 | EF. COM. 413 | 0 | 1 | 0 | 0 | | | +| 7 | 418 | FACTURI NEINTOCMITE | 0 | 1 | 0 | 1 | | | +| 8 | 419 | CLIENTI CREDITORI | 1 | 1 | 0 | 1 | | | +| 49 | 426 | DREPTURI DE PERSONAL NERIDICATE | 1 | 1 | 0 | 0 | | | +| 10 | 4281 | ALTE DATORII IN LEG.CU PERS. | 1 | 0 | 0 | 0 | | | +| 11 | 4282 | ALTE CREANTE IN LEGATURA CU PERSONALUL | 0 | 0 | 0 | 0 | | | +| 65 | 4511 | DECONTARI IN CADRUL GRUPULUI | 2 | 1 | 0 | 0 | 1 | 2013 | +| 76 | 4551 | ACTIONARI | 0 | 1 | 0 | 0 | | | +| 68 | 456 | DECONTARI CU ACTIONARII | 0 | 1 | 0 | 0 | | | +| 52 | 457 | DIVIDENDE 457 | 1 | 1 | 0 | 0 | | | +| 14 | 461 | DEBITORI DIVERSI | 0 | 1 | 0 | 0 | | | +| 15 | 462 | CREDITORI DIVERSI | 1 | 1 | 0 | 0 | | | +| 51 | 471 | CHELTUIELI IN AVANS | 0 | 1 | 0 | 0 | | | +| 67 | 472 | VENITURI IN AVANS | 1 | 1 | 0 | 0 | | | +| 75 | 4754 | SUBVENTII INVESTITII | 1 | 1 | 0 | 0 | | | +| 64 | 491 | PROVIZ.DEPREC.CREANTE-CLIENTI | 0 | 0 | 0 | 0 | | | +| 74 | 5081 | DEPOZITE BANCARE | 0 | 0 | 0 | 0 | | | +| 18 | 5121 | BANCA LEI | 0 | 0 | 0 | 0 | | | +| 50 | 5122 | CONT CURENT GARANTII BRD | 0 | 0 | 0 | 0 | | | +| 19 | 5124 | BANCA VALUTA | 0 | 0 | 0 | 0 | | | +| 69 | 5125 | SUME IN CURS DE DECONTARE - POS | 0 | 0 | 0 | 0 | | | +| 70 | 5126 | BANCA LEI TVA DEFALCAT | 0 | 0 | 0 | 0 | | | +| 71 | 5127 | BANCA VALUTA TVA DEFALCAT | 0 | 0 | 0 | 0 | | | +| 20 | 5311 | CASA LEI | 0 | 0 | 0 | 0 | | | +| 21 | 5314 | CASA VALUTA | 0 | 0 | 0 | 0 | | | +| 22 | 542 | ACHIZITORI | 0 | 1 | 0 | 0 | | | +| 58 | 8051 | DOBANDA EXTRABILANTIER | 0 | 1 | 0 | 0 | | | + +Total randuri: 47. + +## Conturi cu CU_INREGISTRARI = 1 + +1621, 167, 232, 234, 261, 2678, 2691, 401, 403, 404, 408, 409, 4091, 4092, 4093, 4094, 4111, 4118, 413, 418, 419, 426, 4511, 4551, 456, 457, 461, 462, 471, 472, 4754, 542, 8051 diff --git a/docs/conturi_cu_analitice.md b/docs/conturi_cu_analitice.md new file mode 100644 index 0000000..ac1e94a --- /dev/null +++ b/docs/conturi_cu_analitice.md @@ -0,0 +1,166 @@ +# Conturi cu analitice in balanta SAGA - analitic in ROA sau partener? + +Propunerea mea e in coloana **Propus**. Marius: corecteaza direct in tabel (scrie ANALITIC sau PARTENER) +sau spune-mi ce schimbi. Sursa: `balanta_FUNDATIA.csv`, `balanta_MASTERJOB.csv`. + +- **ANALITIC** = ramane cont analitic in planul de conturi ROA (acont 4 caractere) si in balanta. +- **PARTENER** = nu se creeaza analitic in ROA; se genereaza rand `FACTURA` per analitic, cu partener + nou (cod fiscal = codul SAGA, ex `401.00027`), iar soldul intra pe contul sintetic cu id_partd/id_partc. + +## FUNDATIA + +| Cont | Denumire | Nr. analitice | Sold total | Propus | +|---|---|---|---|---| +| 1171 | REZULTATUL REPORTAT - PROFITUL NEREP./ PIREDE | 1 | 773,608.10 | **ANALITIC** | +| 1171.01 | REZ. REPORTAT PT. EXCEDENT NEREP. SAU DEFICIT | 12 | 773,608.10 | **ANALITIC** | +| 1211 | EXCEDENT SAU DEFICIT PRIVIND AFSP | 1 | 150,933.49 | **ANALITIC** | +| 2111 | TERENURI | 1 | 100,000.00 | **ANALITIC** | +| 212 | CONSTRUCTII | 5 | 1,408,257.53 | **ANALITIC** | +| 2814 | AMORT. ALTOR IMOBILIZARI CORP. | 1 | -20,633.36 | **ANALITIC** | +| 401 | FURNIZORI | 10 | -314,703.58 | **PARTENER** | +| 4092 | FUR.-DEBIT PT.PRESTARI SERVICII | 3 | 809.33 | **PARTENER** | +| 4111 | CLIENTI | 1 | 15,126.48 | **PARTENER** | +| 446 | ALTE IMPOZITE SI TAXE | 1 | 485.00 | **ANALITIC** | +| 4551 | ASOCIATI-CONTURI CURENTE | 2 | -1,571,531.33 | **PARTENER** | +| 461 | DEBITORI DIVERSI | 6 | 477,938.37 | **PARTENER** | +| 462 | CREDITORI DIVERSI | 3 | -3,400,771.00 | **PARTENER** | +| 5121 | CONTURI LA BANCA IN LEI | 1 | 81,966.80 | **PARTENER** | +| 5124 | CONTURI LA BANCA IN DEVIZE | 1 | 2,492,540.28 | **PARTENER** | +| 5125 | SUME IN CURS DE DECONTARE | 2 | 160,509.43 | **PARTENER** | + +### Detaliu analitice propuse PARTENER + +**401 FURNIZORI** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 401.00004 | GTC AUTO TRADE | 0.00 | 0.30 | +| 401.00018 | HOSTVISION SRL | 0.00 | 614.10 | +| 401.00043 | BRIT MOTOR AG SRL | 0.00 | 6,640.62 | +| 401.00045 | TRACOM IMPEX S.R.L. | 0.00 | 1,392.75 | +| 401.00049 | APA CANAL ILFOV | 0.00 | 1,126.82 | +| 401.00050 | SC CEGIM SRL | 0.00 | 5,599.99 | +| 401.00051 | S.C. CRAMA SPARLENI SRL | 0.00 | 420.00 | +| 401.00053 | POPESCU LUMINITA-MACOVICIUC VERONICA | 0.00 | 298,530.00 | +| 401.00054 | DEDEMAN SRL | 0.00 | 190.00 | +| 401.00055 | AGROMECANIC IMPEX SRL | 0.00 | 189.00 | + +**4092 FUR.-DEBIT PT.PRESTARI SERVICII** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 4092.1 | HOSTVISION | 547.65 | 0.00 | +| 4092.2 | ROMARG | 217.70 | 0.00 | +| 4092.3 | HORVARTH ALINA GABRIELA PROMISIUNE VZ-C | 43.98 | 0.00 | + +**4111 CLIENTI** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 4111.00004 | EM INTERNATIONAL SERVICES GROUP S.R.L. | 15,126.48 | 0.00 | + +**4551 ASOCIATI-CONTURI CURENTE** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 4551.01 | IONESCU VALENTIN GHEORGHE | 0.00 | 1,383,131.33 | +| 4551.02 | EURO ANTR RO12 PIRB 4250 7735 C 0200 1000 | 0.00 | 188,400.00 | + +**461 DEBITORI DIVERSI** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 461.01 | SISTEME INTERNATIONALE DE AFACERI | 15,031.49 | 0.00 | +| 461.02 | IMPRUMUT ASOC. NO-ADD | 10,800.00 | 0.00 | +| 461.03 | TEMPLUM | 29,445.23 | 0.00 | +| 461.04 | DEBITOR EURO ANTREPRENOR | 417,000.01 | 0.00 | +| 461.06 | ADRIAN CRISTESCU | 5,000.00 | 0.00 | +| 461.07 | FUNDATIA DOMENIU OTETELESANU | 661.64 | 0.00 | + +**462 CREDITORI DIVERSI** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 462.01 | TEMPLUM PLUS | 0.00 | 988,640.00 | +| 462.04 | CREDITOR EURO PRO CONSTRUCT | 0.00 | 1,869,897.00 | +| 462.05 | MODREA ALAIN FLORIN | 0.00 | 542,234.00 | + +## MASTERJOB + +| Cont | Denumire | Nr. analitice | Sold total | Propus | +|---|---|---|---|---| +| 117 | REZULTATUL REPORTAT | 8 | 44,795.92 | **ANALITIC** | +| 2111 | TERENURI | 1 | 439,966.60 | **ANALITIC** | +| 371 | MARFURI | 1 | 38,850.00 | **ANALITIC** | +| 401 | FURNIZORI | 18 | -547,108.99 | **PARTENER** | +| 4092 | FURNIZORI — DEBITORI PT. PRESTARI DE SERVICII | 1 | 4.00 | **PARTENER** | +| 4111 | CLIENTI | 1 | 12,000.00 | **PARTENER** | +| 441 | IMPOZITUL PE PROFIT SI ALTE IMPOZITE | 1 | -2,567.00 | **ANALITIC** | +| 447 | FONDURI SPECIALE TAXE SI VARSAMINTE ASIMILATE | 1 | -47.00 | **ANALITIC** | +| 4551 | ACTIONARI/ASOCIATI - CONTURI CURENTE | 2 | -751,724.61 | **PARTENER** | +| 461 | DEBITORI DIVERSI | 3 | 69,289.00 | **PARTENER** | +| 462 | CREDITORI DIVERSI | 4 | -9,810.00 | **PARTENER** | +| 5121 | CONTURI LA BANCA IN LEI | 2 | 15,578.45 | **PARTENER** | +| 5124 | CONTURI LA BANCA IN VALUTA | 2 | 1,060,090.96 | **PARTENER** | +| 5125 | SUME IN CURS DE DECONTARE | 1 | 0.50 | **PARTENER** | + +### Detaliu analitice propuse PARTENER + +**401 FURNIZORI** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 401.00001 | MEDIAROM COMUNICATIONS | 0.00 | 14,293.76 | +| 401.00003 | TEMPLUM PLUS | 0.00 | 500.00 | +| 401.00006 | BIROU INDIVIDUAL NOTARIAL GEORGE TRAGONE | 0.00 | 952.00 | +| 401.00007 | ACVATIC TES S.R.L. | 0.00 | 439,966.60 | +| 401.00008 | DREAM FISH S.R.L. | 0.00 | 38,850.00 | +| 401.00009 | LEROY MERLIN ROMANIA SRL C | 0.00 | 2,902.91 | +| 401.00010 | SERVICE ONLAPTOP S.R.L. | 0.00 | 1,230.00 | +| 401.00011 | PET PRODUCT SRL | 0.00 | 445.05 | +| 401.00012 | BIROU INDIVIDUAL NOTARIAL PIELEANU DANIELA | 0.00 | 4,879.00 | +| 401.00013 | CREATIV EXPERT CONSTRUCT S.R.L. | 0.00 | 3,300.00 | +| 401.00014 | **(lipsa denumire in PDF)** | 0.00 | 16,802.46 | +| 401.00015 | ANDREEA BEATRICE VASILE | 0.00 | 10,000.00 | +| 401.00017 | TIRES AND PARTS SRL | 0.00 | 1,245.00 | +| 401.00023 | ANGLO CARS S.R.L. | 0.00 | 3,700.90 | +| 401.00024 | DAW BENTA SRL | 0.00 | 1,948.01 | +| 401.00025 | ROMSYSTEMS S.R.L. | 0.00 | 1,380.40 | +| 401.00026 | UNIVERSAL GRUP SRL | 0.00 | 1,380.90 | +| 401.00027 | SEBASTIAN CONSTRUCTII MONTAJ SRL | 0.00 | 3,332.00 | + +**4092 FURNIZORI — DEBITORI PT. PRESTARI DE SERVICII** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 4092.01 | ICI | 4.00 | 0.00 | + +**4111 CLIENTI** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 4111.00001 | NEW HOME CONSTRUCT S.A. | 12,000.00 | 0.00 | + +**4551 ACTIONARI/ASOCIATI - CONTURI CURENTE** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 4551.01 | IONESCU VALENTIN | 0.00 | 729,308.61 | +| 4551.02 | TOMA IONEL VIOREL RO55 RZBR 0000 0600 1338 1717 | 0.00 | 22,416.00 | + +**461 DEBITORI DIVERSI** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 461.01 | SISTEME INTARNATIONALE DE AF. | 8,289.00 | 0.00 | +| 461.02 | HABITAT SI AMBIENT | 20,000.00 | 0.00 | +| 461.03 | DEBITORI DIVERSI | 41,000.00 | 0.00 | + +**462 CREDITORI DIVERSI** + +| Analitic SAGA | Denumire (nume partener) | Sold D | Sold C | +|---|---|---|---| +| 462.01 | CREDITORI DIVERSI -IONESCU ALINA | 0.00 | 3,350.00 | +| 462.02 | CREDITORI DIVERSI - REZIDENT COM | 0.00 | 700.00 | +| 462.03 | CREDITORI DIVERSI - IONESCU VALENTIN | 0.00 | 760.00 | +| 462.05 | CREDITOR C.S.C. | 0.00 | 5,000.00 | diff --git a/docs/decizii_import.md b/docs/decizii_import.md new file mode 100644 index 0000000..f548a2d --- /dev/null +++ b/docs/decizii_import.md @@ -0,0 +1,116 @@ + +## 11. Trezorerie: banca si casa (512x / 531x) - PARTENERI, nu analitice +Stabilit 20.09.2026. + +- **Conturi bancare `512x`** (5121 lei, 5124 devize, 5125 sume in curs de decontare): analiticele SAGA + **nu** devin analitice in ROA. Pentru fiecare analitic se creeaza un **partener cu numele exact al + analiticului** (numele contului bancar, ex `RO73 BACX 0000 0008 7243 0001`, `PIRAEUS BANK - RON`), + cod fiscal = codul SAGA (`5121.01`), si un rand `FACTURA` pe contul sintetic. +- **Casa `531x`**: se creeaza partenerul **`CENTRALA`** (casa centrala), cod fiscal = codul contului + (`5311`). Contul nu are analitice in balantele astea - un singur rand `FACTURA` pe sintetic. + +## 12. Partener fara denumire in balanta +Daca analiticul nu are denumire in PDF (ex MASTERJOB `401.00014`), partenerul se creeaza cu numele +**`FURNIZOR `** (`FURNIZOR 401.00014`) si cod fiscal `401.00014`. Contabilitatea il +identifica dupa cod si il corecteaza in ROA. Nu se ghiceste numele. + +## 13. Postari directe pe contul sintetic (analitic de diferenta) +SAGA permite inregistrari **direct pe contul sintetic**, fara analitic, si in plus **neteaza** D/C la +sintetice. Importul ROA construieste sinteticul ca **suma analiticelor**, deci partea postata direct +pe sintetic s-ar pierde. + +Regula: +1. Diferenta se calculeaza **pe net** (`parinte_D - parinte_C` fata de `SUM(copii_D) - SUM(copii_C)`), + pentru ca gross-ul parintelui e netat de SAGA si nu e recuperabil. +2. Diferenta **net zero** = doar netare SAGA, se ignora (ex FUNDATIA `1171.01`: -739.831,67 pe ambele + laturi, net 0). +3. Diferenta **net diferita de zero** = postare reala pe sintetic: se adauga un **analitic nou de + diferenta**, cu suma pusa pe latura semnului diferentei, si se **raporteaza explicit** in + `verificare_.md` (nu se ajusteaza analiticele existente). +4. La conturile devenite PARTENERI, diferenta devine un **partener de diferenta**, nu un analitic. + +Cazuri gasite la importul 12/2025: +| Firma | Cont | Diferenta net | Tratament | +|---|---|---|---| +| FUNDATIA | 1171.01 | 0,00 (doar netare) | se ignora | +| MASTERJOB | 117 | +2.635,87 debit | analitic nou de diferenta | +| MASTERJOB | 5121 | +152,16 debit | partener de diferenta (5121 e cont cu parteneri) | + +## 14. Trezorerie (512x / 531x): parteneri pe randuri BALANTA, FARA randuri FACTURA +Stabilit 20.09.2026, inlocuieste partea de forma din pct. 11 (regula de continut ramane). + +Conturile de banca si casa **au parteneri, dar nu au facturi**: apar in balanta de verificare si in +balanta de parteneri, niciodata in registrul de facturi. + +In xlsx: +- **Nu** se genereaza randuri `TIP=FACTURA` pe `512x` / `531x`. +- Se genereaza cate un rand `TIP=BALANTA` **per cont bancar / casa**, pe contul sintetic + (`acont` gol), cu `nume` = denumirea analiticului SAGA (numele contului bancar, `CENTRALA` la + casa) si `cod_fiscal` = codul SAGA (`5121.01`, `5311`), `totdeb`/`totcred` = sumele totale ale + analiticului respectiv. + +Confirmare din codul ROA (`COMUN\ferestre\frm_initializare_facturi_balanta.sc2:1104-1107`), la +celalalt flux de import (balanta prin `conturi_roa.dbf`), unde exista doua liste distincte: +- `lcListaConturiBalP` (balanta de parteneri): `401,404,408,409,4091,4092,4093,4111,418,419,461,462,4551,`**`5311,5121,5124`** +- `lcListaConturiIregP` (inregistrari/facturi): aceeasi lista **fara** `5311,5121,5124` + +`5125` nu figureaza in niciuna dintre liste - de tratat separat. + +### Forma concreta in xlsx: randuri FACTURA (decis 20.09.2026) +Formularul de import xlsx **nu suporta parteneri pe randurile `BALANTA`**: +- `:828` goleste `denumire` cand `tip = 'BALANTA'` (o muta in `explicatia`) +- `:867` construieste nomenclatorul de parteneri doar din randurile `WHERE ALLTRIM(tip) = 'FACTURA'` + +Ca sa nu modificam formularul, trezoreria se pune **pe randuri `FACTURA`**, ca orice cont cu +parteneri: partenerul se creeaza corect, `id_partd`/`id_partc` se completeaza, iar +`balanta_parteneri` se reconstruieste din `ireg_parteneri` (`:1685-1695`), deci cifrele ies exact. + +Efect secundar acceptat: pe conturile de trezorerie raman documente de tip FACTURA +(`id_fdoc = 42`, `:528`) care nu sunt facturi reale. Nu deranjeaza balanta de parteneri. + +Regula de continut ramane cea de la pct. 11: un partener per cont bancar, cu numele analiticului +(`RO45 PIRB ...`, `PIRAEUS BANK - RON`), iar la casa partenerul `CENTRALA`. + +### Sensul soldului la trezorerie +Randurile FACTURA primesc latura dintr-o **lista fixa in cod** (`:379`): +`401, 404, 462, 419, 408, 4551` -> credit; **tot restul -> debit**. +Un cont bancar cu sold creditor (descoperit de cont) nu se poate exprima printr-un rand FACTURA: +se lasa fara rand FACTURA, iar randul `BALANTA` il duce pe credit, unde formularul ii pune automat +partenerul `NEREPARTIZAT` (`:415-431`). Se raporteaza cazul, ca sa fie corectat manual in ROA. +Caz gasit: MASTER `5121.01 PIRAEUS BANK - RON`, sold creditor 20,80. + +## 15. 512x: analitice SI parteneri; 5125 doar analitice +Revizuit 20.09.2026 (inlocuieste forma din pct. 11 si 14 pentru aceste conturi). + +- **`5121`, `5124`** (conturi bancare): analiticele **raman analitice** in planul de conturi si in + balanta, **si in plus** fiecare analitic primeste un partener. Concret, pentru fiecare analitic + se scriu DOUA randuri, pe acelasi `(cont, acont)`: + - un rand `TIP=BALANTA` cu `acont` completat si `totdeb`/`totcred` = sumele totale ale analiticului; + - un rand `TIP=FACTURA` cu **acelasi `acont`**, `nume` = denumirea analiticului (numele contului + bancar), `cod_fiscal` = codul SAGA (`5121.01`), `sold` = soldul analiticului. + + `acont` trebuie sa fie acelasi pe ambele randuri: formularul scade randurile FACTURA din randul + BALANTA care are acelasi `(cont, acont, latura)` (`:415-431`). Cu `acont` diferit suma s-ar + dubla si ar aparea un rest negativ pe `NEREPARTIZAT`. +- **`5311`** (casa, fara analitice): rand `BALANTA` pe `5311` (acont gol) + rand `FACTURA` pe + `5311` (acont gol), partener `CENTRALA`. +- **`5125`**: **doar analitice**, fara parteneri. Se trateaza ca orice cont obisnuit cu analitice. +- Un analitic cu soldul pe latura opusa laturii fixate in cod (`:379`, trezoreria merge pe debit) + nu primeste rand FACTURA; ramane doar randul BALANTA si formularul ii pune `NEREPARTIZAT`. + Caz gasit: MASTER `5121.01 PIRAEUS BANK - RON`, sold creditor 20,80. + +## 16. Regula generala: randul FACTURA trebuie sa aiba acelasi `acont` ca randul BALANTA pe care il consuma +Confirmat 20.09.2026. + +Formularul grupeaza randurile `FACTURA` pe `(cont, acont, latura)` si **scade** suma lor din randul +`BALANTA` cu exact aceeasi cheie; restul ramane pe partenerul `NEREPARTIZAT`, iar daca randul +`BALANTA` lipseste, il creeaza el (`frm_initializare_facturi_balanta.sc2:415-431`). + +Consecinte: +- `acont` gol pe `FACTURA` + `acont` completat pe `BALANTA` = cheie diferita: suma **se dubleaza** + (analiticul ramane intreg in balanta si se mai adauga un rand negativ pe sintetic, pe + `NEREPARTIZAT`). Greseala tacuta, nu da eroare. +- De aceea: cont cu parteneri **fara** analitice in ROA (401, 4092, 4111, 461, 462, 4551) -> + ambele randuri cu `acont` gol. Cont cu parteneri **si** analitice in ROA (5121, 5124) -> + ambele randuri cu acelasi `acont`. +- Latura conteaza si ea: un rand FACTURA pe debit nu atinge randul BALANTA de pe credit. diff --git a/docs/plan_solduri2roa.md b/docs/plan_solduri2roa.md new file mode 100644 index 0000000..6458a81 --- /dev/null +++ b/docs/plan_solduri2roa.md @@ -0,0 +1,58 @@ +# Plan: balante SAGA (PDF) -> xlsx de initializare ROA + +Proiect: `D:\ROA\IMPORT2ROA\solduri2roa` +Obiectiv prioritar: doua fisiere xlsx gata de importat in ROACONT pentru FUNDATIA si MASTER, luna 12/2025. +Obiectiv secundar (pasul 2): program reutilizabil de conversie SAGA -> xlsx ROA. + +Deciziile de mapare: `decizii_import.md`. Semantica formularului de import: `raport_form_init_balanta.md`. + +## Etapa 1 - extragere fidela din PDF (lane `pdf-extract`) +`extract_balanta.py` (pdfplumber, pe coordonate) -> `balanta_FUNDATIA.csv`, `balanta_MASTERJOB.csv` +cu `cont;denumire;prec_d;prec_c;rulaj_d;rulaj_c;total_d;total_c;sold_d;sold_c;este_total`. +Poarta de trecere (nu se avanseaza cat timp pica): +- `total_d = prec_d + rulaj_d`, `total_c = prec_c + rulaj_c` pe fiecare cont +- `sold_d - sold_c = total_d - total_c` pe fiecare cont +- `SUM(sold_d) = SUM(sold_c)` pe conturile frunza +- suma analiticelor = parintele, pe fiecare nivel +Un esec = parser gresit, nu date gresite: se repara parserul, nu cifrele. + +## Etapa 2 - semantica formularului (lane `form-init-balanta`) +Analiza `COMUN\ferestre\frm_initializare_facturi_balanta.sc2`: coloane obligatorii, validari +blocante, crearea partenerului dupa `cod_fiscal` (si daca respinge un "CUI" de forma `401.00027`), +regula `id_partd`/`id_partc`, lungimi `cont`/`acont`, rolul `CONFIG_CONT_IREG`. +Risc principal de oprit aici: o validare de CUI care refuza `401.00027`. + +## Etapa 3 - conturile cu parteneri (lane `config-cont-ireg`) +`CONFIG_CONT_IREG` din Oracle local -> lista conturilor cu `CU_INREGISTRARI = 1`. + +## Etapa 4 - maparea in structura ROA +Pentru fiecare firma, din CSV: +1. **Conturi fara parteneri**: se pastreaza doar frunzele. `cont` = primele max 4 caractere, + `acont` = restul cifrelor concatenate (max 4). Un rand `BALANTA` per frunza, cu + `totdeb = total_d`, `totcred = total_c`. Daca suma frunzelor difera de parinte -> analitic de + diferenta, raportat explicit. +2. **Conturi cu parteneri** (din etapa 3): un singur rand `BALANTA` pe sintetic (fara `acont`), + cu suma `total_d` / `total_c` a analiticelor, plus cate un rand `FACTURA` per analitic-partener: + `nume` = denumirea analiticului, `cod_fiscal` = `.` din SAGA, + `numar` = analiticul, `sold` = soldul analiticului (cu semnul dat de natura contului), + `data` = 01.12.2025, `datascad` = 31.12.2025. +3. Toate randurile: `an = 2025`, `luna = 12`. +Iesire: `init_FUNDATIA_2025_12.xlsx`, `init_MASTER_2025_12.xlsx`, generate din sablonul +`init_facturi_balanta_note.xlsx` cu randurile de instructiuni sterse. + +## Etapa 5 - verificare inainte de predare +- `SUM(totdeb) = SUM(totcred)` pe tot xlsx-ul +- pentru fiecare cont cu parteneri: `SUM(sold FACTURA) = soldul sintetic din balanta` +- fiecare cont din balanta apare exact o data (frunza) in xlsx; niciun cont pierdut +- `cont` <= 4 caractere, `acont` <= 4 caractere, fara dubluri `cont+acont` +Raport: `docs\verificare_.md`, cu totalurile din balanta alaturi de totalurile din xlsx. + +## Etapa 6 - git +`git init`, commit, push pe `gitea.romfast.ro:romfast/solduri2roa.git` (push-to-create). +Se comit: scripturile, `docs\`, CSV-urile si xlsx-urile generate. PDF-urile: da (sunt sursa, 30 KB). + +## Pasul 2 (dupa import) - convertorul reutilizabil +Generalizarea etapelor 1 + 4 intr-un singur script cu parametri (firma, an, luna, sursa PDF sau +xlsx SAGA), cu regulile din `decizii_import.md` scoase intr-un fisier de configurare +(conturi cu parteneri, maparea analiticelor). Nu se porneste inainte ca cele doua importuri sa +fie validate in ROA. diff --git a/docs/prompt_initial.md b/docs/prompt_initial.md new file mode 100644 index 0000000..c4443e1 --- /dev/null +++ b/docs/prompt_initial.md @@ -0,0 +1,12 @@ +# Prompt initial pentru agentii opencode - proiect solduri2roa + +Esti EXECUTANT, nu arhitect. Lucrezi in D:\ROA\IMPORT2ROA\solduri2roa. + +Reguli: +- Python 3.13 se apeleaza cu `py` (nu `python`). Librarii deja instalate: pdfplumber, openpyxl. +- Nu folosi NICIODATA `sed -i`. Scrie fisiere cu redirectare/heredoc sau cu Python. +- Nu da commit (git/svn) si nu modifica nimic in afara D:\ROA\IMPORT2ROA\solduri2roa (D:\ROA\ROACONT e read-only pentru tine). +- Codul e simplu si scurt: fara clase inutile, fara framework-uri, fara dependinte noi. +- Nu inventa date. Daca o valoare nu se poate extrage sigur, o raportezi ca problema, nu o ghicesti. +- Scrii raportul cerut in docs\raport_.md, scurt, cu fapte si numere, fara povestiri. +- Ultimul mesaj: `GATA ` sau `BLOCAT : motiv`. diff --git a/docs/raport_config-cont-ireg.md b/docs/raport_config-cont-ireg.md new file mode 100644 index 0000000..16ee3c8 --- /dev/null +++ b/docs/raport_config-cont-ireg.md @@ -0,0 +1,25 @@ +# Raport config-cont-ireg + +Read-only. Doar SELECT. Nu s-a modificat nimic in baza; nu s-a scris in D:\ROA\ROACONT. + +## 1. Facut + +- Livrat: `D:\ROA\IMPORT2ROA\solduri2roa\docs\config_cont_ireg.md` — schema sursa, comanda de conectare, DESC, toate cele 47 randuri, lista CU_INREGISTRARI=1. +- Citire: `MARIUSM_AUTO.CONFIG_CONT_IREG` prin `sqlplus -S "MARIUSM_AUTO/ROMFASTSOFT@ROA_CENTRAL"`, TNS_ADMIN=`D:\ROA\instantclient_19_18`. +- DSN `ROA_CENTRAL` (10.0.20.121:1521/ROA) din `D:\ROA\instantclient_19_18\tnsnames.ora:206`. Parola din `D:\ROA\ROACONT\docs\oracle_parola_standard.secret` (=`ROMFASTSOFT`, si in `COMUN\utile\Teste\test_init_env_auto.prg:22`). + +## 2. Verificari + +- Conectare verificata: `select user from dual` -> `MARIUSM_AUTO`. +- Numarare: `select count(*) from config_cont_ireg` -> 47 (toate scrise in livrabil). +- Coloana ceruta "denumire" nu exista; denumirea este `EXPLICATIE` (notat in livrabil). +- Tabela are in plus: `FEL_CONT`, `CU_VENCHELT`, `CU_PROC_TVA`, `LUNAI`, `ANI` (incluse in livrabil; LUNAI/ANI doar pe randul 4511). +- Nu au fost rulate teste VFP. + +## 3. Nefacut / blocat + +- Nimic in afara scopului. Nu am scris raportul in `D:\ROA\ROACONT` (interzis explicit de sarcina), l-am pus in folderul de livrare. + +## 4. Stare periculoasa + +- Niciuna: zero scrieri in baza, niciun fisier editat in ROACONT, niciun proces ramas. diff --git a/docs/raport_form_init_balanta.md b/docs/raport_form_init_balanta.md new file mode 100644 index 0000000..a54de33 --- /dev/null +++ b/docs/raport_form_init_balanta.md @@ -0,0 +1,217 @@ +# Semantica importului `init_facturi_balanta_note.xlsx` + +Analiza read-only. Sursa de cod: `D:\ROA\ROACONT\COMUN\ferestre\frm_initializare_facturi_balanta.sc2` +(liniile citate sunt cele din fisierul text FoxBin2Prg). Fara analize speculative. + +## Fluxul + +Butonul **Import** (`cmdNoteFacturiBalanta`, optiunea 1) executa in ordine: + +1. `VerificaImport()` - `frm...sc2:2354`, metoda la `2292-2310`. +2. `ExportDate()` - `frm...sc2:2360`, metoda la `738-993`. +3. `Creeazanote()` - `frm...sc2:2364`, metoda la `241-733`. +4. `ModificaNote()` sau `Scrienote()` - `frm...sc2:2368-2371`. + +`ExportDate` citeste xlsx-ul in cursorul `cFacturiTemp` (`frm...sc2:760-774`) si lasa in urma +cursorul `cFacturi` (`frm...sc2:825-847`). `Creeazanote` transforma `cFacturi` in `actactan` +(note in Registrul Jurnal, `id_set = 90024`, `frm...sc2:258`). + +**Maparea coloanelor este positionala**, nu dupa numele din capul de tabel: `appendfromxlsx` +ia campurile cursorului cu `AFIELDS` in ordine (`appendfromxlsx.prg:111-135`) si scrie pe rand. +De aceea numele xlsx difera de numele campului: + +| xlsx | cursor `cFacturiTemp` | citat | +|---|---|---| +| nume | denumire | `frm...sc2:761` (ord. camp 10) | +| numar | nract | `frm...sc2:760` (ord. 7) | +| data | dataact | `frm...sc2:760` | +| explicatia | explicatie | `frm...sc2:762` | +| **sold** | **valoare** | `frm...sc2:765` | +| **soldval** | **totval** | `frm...sc2:765` | +| **soldtvaneex** | **tva** | `frm...sc2:765` | +| **acont4428neex** | **acont4428** | `frm...sc2:765` | + +Maparea sold/soldval/soldtvaneex -> valoare/totval/tva e confirmata si de codul comentat +`frm...sc2:781-799` (`sold -> valoare`, `soldtvaneex -> tva`, `soldval -> totval`). + +--- + +## 1. Randurile TIP=BALANTA: totdeb/totcred + +**Sunt SUME TOTALE cumulate** (sold initial + rulaje), nu solduri nete. In sablon: +"Total sume debitoare BALANTA" / "Total sume creditoare BALANTA" (Sheet1, rand 1). Comentariul +din fluxul inrudit o spune explicit: `TOTDEB/TOTCRED = sume totale (sold la 1 ianuarie + rulaj +precedent anual + rulaj lunar)` (`frm...sc2:1034`). + +Ce face codul cu ele: +- Le transforma in cate o linie separata, nu intr-o diferenta: `totdeb as valoare` pe latura D, + `totcred as valoare` pe latura C, unite cu UNION ALL (`frm...sc2:350-356`). +- Latura (D/C) pentru BALANTA vine din union-ul de mai sus, NU din lista de la `383` (lista 401, + 404, 462, 419, 408, 4551 -> C se aplica doar peste `cFacturiTemp`, care la acel moment contine + doar randuri FACTURA; `frm...sc2:381-383`). +- Nota generata: `id_fdoc = 69` (SOLD) pentru BALANTA, fata de 42 (FACTURA) (`frm...sc2:508`). +- Semnul: daca `tipDC = 'C'` -> contul intra pe credit (`pcScc = pcCont`, `pcAscc = pcAcont`); + daca `tipDC = 'D'` -> pe debit (`pcScd = pcCont`, `pcAscd = pcAcont`) (`frm...sc2:551-579`). +- **Contrapartida: goala.** Partea opusa rămâne `''` (`pcScd/pcAscd` gol pe latura C, + `pcScc/pcAscc` gol pe latura D - `frm...sc2:553-556, 567-570`). Nu exista cont de sold + initial (891/892) in cod. Nota de BALANTA este **unilaterala**, cate o linie per cont/latura. +- Suma postata = soldul BALANTA minus TVA-ul neexigibil de pe aceeasi linie (pentru BALANTA + `tva = 0`, deci suma ramane `valoare`) (`frm...sc2:493, 504-506, 531-546`). +- Daca un cont are si totdeb si totcred nenule, se genereaza doua linii distincte. + +## 2. Randurile TIP=FACTURA + +**Coloane obligatorii** - sablonul le declara (Sheet1, rand 1 / instructiuni): `an, luna, cont, +nr, data, nume, cod_fiscal, sold factura` (optional `facturat/achitat`), `sold TVA Neexigibil` +daca exista; "Pentru FACTURA, OBLIGATORIU completati NUME si COD FISCAL". Codul insa **nu le +valideaza explicit**; singurul filtru dur este `an` numeric nenul (`frm...sc2:846`, +`WHERE !Empty(Val(Transform(an)))`). Un rand fara `an` este ignorat tacit. + +**Partenerul** se creeaza/gaseste astfel: +- `ExportDate` grupeaza randurile FACTURA dupa `denumire, cod_fiscal, reg_com` (`frm...sc2:865-869`) + si adauga mereu un partener `NEREPARTIZAT` (`frm...sc2:871-877`). +- `CompleteazaParteneriROA` (`oproceduri_import.prg:5571-5910`): normalizeaza codul + (`Upper`, fara spatii, `oproceduri_import.prg:5624`); daca lungimea <= 3, codul devine `''` si + cautarea se face **dupa denumire** (`oproceduri_import.prg:5626-5628, 5639-5650`). +- Cauta intai dupa cod exact (`5638-5641`), apoi dupa `NormalizeazaCUI` (`5643-5646`). Daca nu + gaseste, **creeaza partener nou** cu `pack_def.adauga_partener` (`5667-5717`), folosind codul + fiscal ca atare (`5677`), `tip_persoana = 1` daca lungimea < 13, altfel 2 (`5686`). +- **Nu exista validare de CUI (checksum/format).** `NormalizeazaCUI` doar face UPPER, scoate + spatiile si taie prefixul `RO` cand restul e numeric (`validare.prg:1679-1699`). Deci + `"401.00027"` rămâne `"401.00027"`; are 9 caractere (>3), este folosit ca `cod_fiscal`, iar + daca nu exista deja, creeaza un partener nou cu acest cod. **Randul nu este respins.** +- `id_part` se intoarce pe randurile FACTURA prin `Update cFacturi Set id_part ... Where + cod_fiscal = ... AND denumire = ... AND reg_com = ...` (`frm...sc2:902`). + +**Documentul/nota generata**: `id_fdoc = 42` (FACTURA) (`frm...sc2:508`), o linie de valoare +(`facturat` sau `valoare`, minus TVA neexigibil) si, daca exista, o linie `ACHITAT` +(`frm...sc2:529-633`), plus notele de TVA neexigibil (`frm...sc2:650-725`). `id_fact` se ia din +`vireg_parteneri` sau din `SEQ_IdFact` (`frm...sc2:262-320`). + +## 3. Legatura FACTURA <-> BALANTA + +Nu se aduna si nu se verifica egalitatea; **BALANTA se reduce cu totalul facturilor**: +- Se insumeaza `facturat - achitat` pe `cont, acont, tipDC` din randurile FACTURA + (`frm...sc2:389-392`); se adauga si soldul de 4428 TVA neexigibil (`frm...sc2:395-402`). +- Pentru fiecare grupa se cauta linia BALANTA pe `cont/acont/tipDC` (`frm...sc2:411-412`) si + `REPLACE valoare WITH valoare - lnSoldFactura` (`frm...sc2:428`). +- Daca linia BALANTA nu exista, se creeaza automat una cu explicatia `DIFERENTA FACTURI` si + partener `NEREPARTIZAT` (`frm...sc2:413-426`). +- `lnSoldFactura = IIF(sold <> 0, sold, valoare)` - daca `facturat-achitat` e 0, foloseste + `SUM(valoare)` (soldul facturii) (`frm...sc2:408`). +- **Nu exista verificare de egalitate si nici eroare la diferenta**; restul rămâne sold + `NEREPARTIZAT`. + +## 4. Lungimi `cont` / `acont` si combinare + +- Cursorul le declara `C(20)` (`frm...sc2:760`); la iesire se aplica `PADR(ALLTRIM(...), 4, ' ')` + (`frm...sc2:826-827`), deci minim 4, fara trunchiere la 4. In baza, `CONFIG_CONT_IREG.CONT` + este `VARCHAR2(4)` (docs/config_cont_ireg.md:24). Practic, sablonul cere `cont` <= 4 si + `acont` <= 4. +- Daca celula `cont` contine un punct (`401.01`), `ExportDate` o separa: `cont = LEFT(pana la + punct)`, `acont = SUBSTR(dupa punct)`, iar `acont`-ul din coloana proprie se pastreaza daca + nu e gol (`frm...sc2:806-816`). +- In nota finala contul sintetic si analiticul sunt **campuri separate**, nu concatenate: + `scd/ascd` si `scc/ascc` (`frm...sc2:639-645`); `pcCont = ALLTRIM(cont)`, + `pcAcont = ALLTRIM(acont)` (`frm...sc2:477-478`). + +## 5. Rolul `CONFIG_CONT_IREG` / `CU_INREGISTRARI` + +- Se citeste `select cont, decode(fel_cont,'0','D','C') as tipdc, cu_inregistrari from + CONFIG_CONT_IREG` (`frm...sc2:435`). Pentru fiecare cont din config, pe liniile BALANTA se + forteaza partenerul `NEREPARTIZAT` (`frm...sc2:438-443`), ca sa se poata genera balanta de + parteneri. +- `cu_inregistrari = 1` marcheaza conturile cu inregistrari de partener. In `Creeazanote`, daca + linia BALANTA are cont in config, `tipdc` de config este opus laturii curente si + `cu_inregistrari = 1`, atunci pe linia opusa se pune `id_factc/id_factd = id_fact` si + `perechec/pereded = nract` (`frm...sc2:582-595`). +- Lista efectiva a conturilor cu `CU_INREGISTRARI = 1` (dump Oracle local) este in + `docs/config_cont_ireg.md:89-91` (401, 403, 404, 408, 409, 4091-4094, 4111, 4118, 413, 418, + 419, 426, 4511, 4551, 456, 457, 461, 462, 471, 472, 4754, 542, 8051, plus 1621, 167, 232, + 234, 261, 2678, 2691). Fluxul de initializare directa are liste echivalente hardcodate: + parteneri-balanta `401,404,408,409,4091,4092,4093,4111,418,419,461,462,4551,5311,5121,5124` + (`frm...sc2:1104`) si inregistrari-parteneri fara 5311/5121/5124 (`frm...sc2:1107`). +- Randurile FACTURA cu partener sunt deci necesare pentru conturile din `CONFIG_CONT_IREG` cu + `cu_inregistrari = 1`; BALANTA pe acele conturi primeste partener de diferenta. + +## 6. Unde se completeaza `id_partd` / `id_partc` + +In `Creeazanote`, dupa regula debit/credit: +- Linia de valoare: `tipDC = 'C'` -> partenerul pe credit (`pnIdPartC = id_part`, + `pnIdPartD = 0`); `tipDC = 'D'` -> pe debit (`pnIdPartD = id_part`, `pnIdPartC = 0`) + (`frm...sc2:551-579`). Motivul e in comentariu: 401 pe credit, 4111 pe debit. +- Linia `ACHITAT`: invers - `tipDC = 'C'` (furnizor) -> partener pe debit; `tipDC = 'D'` + (client) -> pe credit (`frm...sc2:597-630`). +- Liniile de TVA neexigibil: 4428 vs 401/4111, partener pe latura contului de partener + (`frm...sc2:654-678`). +- Suplimentar pentru BALANTA, pe linia opusa, `id_factc/id_factd` din config + (`frm...sc2:582-595`). Insertul in `actactan` le scrie in `id_partd/partd/id_partc/partc` + (`frm...sc2:639-645, 716-721`). + +## 7. Validari care blocheaza / opresc importul (lista scurta) + +- Documente deja importate: doar avertisment de confirmare, nu blocheaza + (`frm...sc2:2292-2310`, mesaj la `2355`). +- `'Nu s-a generat id_fact!'` (`frm...sc2:313`). +- `'Nu s-a gasit/generat id-ul de factura. Se opreste generarea de id-uri!'` (`frm...sc2:323`). +- `'Eroare la adaugarea in clienti ROA ...'` - opreste `CompleteazaParteneriROA` + (`oproceduri_import.prg:5711`). +- Fisier neales: `Getfile` gol -> return (`frm...sc2:751-755`). +- Rand fara `an` numeric: ignorat tacit (`frm...sc2:846`). +- Erori de citire xlsx: `'Nimic de importat'`, `'Foaie inexistenta'` (`appendfromxlsx.prg:24-45, + 139-145`). +- `'Nu recunosc structura de balanta!'` - doar fluxul direct `InitBalanta` (`frm...sc2:1095`). +- Erori Oracle propagate prin `goExecutor.cEroare` (ex. `frm...sc2:292-294, 981`). + +Nu exista validare de completitudine pe coloanele FACTURA (nume/cod_fiscal/numar/data). + +## 8. `soldtvaneex` / `acont4428neex` / `baza..tva..` + +- `soldtvaneex` -> campul cursor `tva`: soldul TVA neexigibil al facturii + (`frm...sc2:765`; mapare in codul comentat `790`). +- `acont4428neex` -> campul cursor `acont4428`: contul analitic 4428 + (`frm...sc2:765`); folosit ca `ascd/ascc` pe liniile de 4428 + (`frm...sc2:656-657, 670-671`). +- `baza21/tva21 ... baza20/tva20` -> `baza..tva..`: baza si TVA neexigibil pe cote + (`frm...sc2:766-772`). Cota se determina in ordinea 21, 11, 19, 9, 5, 24, 20 + (`frm...sc2:679-711`), iar suma TVA-ului pe cote este `pnTottvatax` (`frm...sc2:510`). +- **Cand sunt obligatorii**: numai cand factura are TVA neexigibil (`lnTVA <> 0`, + `frm...sc2:650`). Sablonul cere explicit: "REGISTRE TVA TVA LA INCASARE. Trebuie completat + SOLD TVA NEEXIGIBIL + BAZA SI TVA NEEXIGIBIL pentru ca randul FACTURA sa aiba explicatie TVA + si sa apara in Registrele de TVA". `acont4428neex` se completeaza doar daca e nevoie. + Daca `tva = 0`, nu se genereaza nicio nota de exigibilitate. + +## 9. Contul sintetic din analitice - il creeaza singur (confirmat) + +- Instructiunea din sablon (Sheet1): "La tip BALANTA se completeaza DOAR CONTURILE ANALITICE, + DACA EXISTA, altfel contul sintetic (ex: 419.1 si 419.2 nu si 419). **Importul creeaza automat + contul sintetic din suma analiticelor**". +- Formularul separa `cont.acont` (`frm...sc2:806-816`) si creeaza intrarea de plan conturi + pentru analitic prin `merge into plcont` (`frm...sc2:943-986`). +- Sinteticul propriu-zis se construieste in engine, la scrierea notelor: + `PACK_CONTAFIN.SCRIE_IN_BALANTA` face `BAL` (sintetic) = `SUM(DEBIT)/SUM(CREDIT)` grupat pe + `scd/scc`, si `BALANA` (analitic) grupat pe `scd + ascd` (`ff_2026_09_09_06_COMUN_PACK_CONTAFIN.sql:6894-6957`), + apelat din `final_scriere_act_rul_local` (`...sql:8552-8553`). +- Fluxul direct `InitBalanta` o face explicit in VFP: "Balanta sintetica" = `SUM` grupat pe + `cont2` fara `acont2` (`frm...sc2:1151-1160`), insert in `bal` (`frm...sc2:1188-1200`) si + analitica in `balana` (`frm...sc2:1245-1258`). + +## 10. Randul de start si numele foii + +- `appendfromxlsx(m.lcFile, "cFacturiTemp", "", 2, "Sheet1", .T.)` (`frm...sc2:774`): + `lnStartRows = 2`, deci **randul 1 (capul de tabel) este sarit; citirea incepe de la randul 2**. + Sablonul o confirma: "IMPORTUL INCEPE DE LA RANDUL 2. LASATI RANDUL 1 (CAPUL DE TABEL)". +- Foaia asteptata: **`Sheet1`**, potrivita case-insensitive dupa nume in `get_sheet` + (`appendfromxlsx.prg:605-634`); in fisier `xl/workbook.xml` foaia se numeste `Sheet1`. +- Randurile de instructiuni (2-19 in sablon) sunt citite ca date dar eliminate de filtrul + `an` nenul (`frm...sc2:846`); datele reale incepand cu randul 20 in sablon. + +--- + +## Observatii + +- Ambele directii folosesc acelasi sablon `init_facturi_balanta_note.xlsx` (`frm...sc2:2258`); + optiunea 2 (initializare directa) foloseste insa `InitBalanta`/`InitFacturi`, cu alte fisiere + si alte structuri (`balanta.xlsx`, `facturi.xlsx`). +- Toate citatele de mai sus sunt din fisierul `.sc2` (text), nu din binar. +- Nu s-a modificat nimic in `D:\ROA\ROACONT`. diff --git a/docs/raport_genxlsx.md b/docs/raport_genxlsx.md new file mode 100644 index 0000000..23e2338 --- /dev/null +++ b/docs/raport_genxlsx.md @@ -0,0 +1,65 @@ +# Raport lane `genxlsx` (v2) + +Script: `genereaza_xlsx.py`. Produce pentru fiecare firma xlsx-ul de initializare +(`init__2025_12.xlsx`, un sheet, randul 1 = capul de tabel, fara instructiuni/exemple) +si raportul de verificare (`docs/verificare_.md`). + +## Livrabile +- `init_FUNDATIA_2025_12.xlsx` - 75 randuri (47 BALANTA, 28 FACTURA) +- `init_MASTER_2025_12.xlsx` - 79 randuri (46 BALANTA, 33 FACTURA) +- `docs/verificare_FUNDATIA.md`, `docs/verificare_MASTER.md` +- `genereaza_xlsx.py` + +## Rezultate verificari (toate OK) +| Firma | SUM(totdeb)=SUM(totcred) | frunze pierdute | parteneri | lungimi/dubluri | +|---|---|---|---|---| +| FUNDATIA | 7068369.50 = 7068369.50 (net 0.00) | 0 | OK | OK | +| MASTER | 2318592.91 = 2318592.91 (net 0.00) | 0 | OK | OK | + +## Corectii v2 (fata de v1) +1. **Randul FACTURA `DIFERENTA SINTETIC ` a fost eliminat** de pe conturile cu parteneri. + Formularul scade singur suma randurilor FACTURA din randul BALANTA de pe acelasi + `(cont, acont, latura)` si pune restul pe partenerul `NEREPARTIZAT` pe care il creeaza el + (`frm..sc2:415-431`). Diferenta nu se mai inventa de noi. +2. **Analitice cu sold pe latura opusa nu mai primesc FACTURA.** Latura FACTURA e fixa in cod + (`frm..sc2:379`/'383'): `401,404,462,419,408,4551` -> CREDIT, orice alt cont -> DEBIT. + Analiticul sarit ramane doar in randul BALANTA (pe latura lui corecta) si formularul ii pune + `NEREPARTIZAT`. Fiecare caz e listat in raport (sectiunea 4). +3. **Randul BALANTA reprezinta contul sintetic intreg.** La partenerii cu un singur BALANTA + agregat, `totdeb` = suma `total_d` a tuturor analiticelor + postarea directa pe sintetic + (idem `totcred`), nu doar analiticele pentru care s-a emis FACTURA. +4. **pct. 15 (revizuit 20.09.2026):** + - `5121`/`5124`: analiticele **raman analitice** si in plus primesc partener. Pentru fiecare + analitic se scriu **doua randuri pe acelasi `(cont, acont)`**: un `BALANTA` cu acont si + `totdeb`/`totcred` ale analiticului, si un `FACTURA` cu **acelasi acont**, `cod_fiscal` = + codul SAGA, `sold` = soldul analiticului. Acelasi `acont` e obligatoriu, altfel scaderea din + cod nu se potriveste si suma se dubleaza. + - `5125`: NU mai e cont cu parteneri - doar randuri BALANTA cu acont, fara FACTURA. + - `5311`: BALANTA (acont gol) + FACTURA (acont gol), partener `CENTRALA`. + - `401, 4092, 4111, 461, 462, 4551`: neschimbate - un BALANTA agregat pe sintetic (acont gol) + + cate un FACTURA per analitic (acont gol). + +## Ce ramane pe `NEREPARTIZAT`, per cont (sectiunea 3 din verificari) +`net sintetic - SUM(sold FACTURA cu semn) = analitice sarite + postare directa pe sintetic`. +Rezultat: toate conturile ies 0, mai putin MASTER `5121`: + +| cont | SUM FACTURA | net sintetic | sarite | postare directa | NEREPARTIZAT asteptat | diferenta | +|---|---|---|---|---|---|---| +| MASTER 5121 | 15599.25 | 15730.61 | -20.80 (`5121.01` creditor) | +152.16 | 131.36 | 131.36 | + +- MASTER `5121.01 PIRAEUS BANK - RON` (sold creditor 20,80): fara FACTURA, doar + `BALANTA 5121 acont 01` pe credit -> formularul ii pune `NEREPARTIZAT`. +- MASTER `5121` postare directa +152.16: rand `BALANTA 5121 acont 99` `DIFERENTA SINTETIC SAGA` + (fara FACTURA) -> `NEREPARTIZAT`. + +## Randuri de diferenta (pct. 13-15) generate +- MASTER `117` (nepartener): +2635.87 -> rand `BALANTA` cont 117, acont `99`, + nume `DIFERENTA SINTETIC SAGA`. +- MASTER `5121` (banca): +152.16 -> rand `BALANTA` cont 5121, acont `99`, fara FACTURA. +- FUNDATIA: niciunul (1171.01 are diferenta net zero - doar netare SAGA). + +## Observatii +- SUM(totdeb) difera de `Totaluri.total_d` din PDF (FUNDATIA +739831.67, MASTER +20.80): + gross-ul sinteticelor netate de SAGA nu se poate reconstrui din frunze; netul coincide exact. +- Coloana `explicatia` (control D/C) este goala in xlsx-ul final. +- Nu s-a facut niciun commit. diff --git a/docs/raport_pdf_extract.md b/docs/raport_pdf_extract.md new file mode 100644 index 0000000..398df69 --- /dev/null +++ b/docs/raport_pdf_extract.md @@ -0,0 +1,57 @@ +# Raport pdf-extract - balante SAGA 31.12.2025 + +Script: `extract_balanta.py` (pdfplumber, extract_words pe coordonate; NU pdftotext). +Rulare: `py extract_balanta.py "" ""`. + +## Volum extras + +| Firma | PDF | randuri CSV | conturi | randuri total | +|---|---|---|---|---| +| FUNDATIA | IBB 31.12.2025.pdf | 88 | 82 | 6 | +| MASTERJOB | MJC 31.12.2025.pdf | 88 | 81 | 7 | + +Conturi duplicate: niciunul. Randuri de continuare de denumire lipite corect +(ex: `1171` = "REZULTATUL REPORTAT - PROFITUL NEREP./ PIREDERE NEACOP."). + +## Rezultat verificari + +`frunze` = cont care nu e parinte. `radacini` = cont al carui parinte nu apare in balanta. +SAGA neteaza D/C la conturile sintetice, deci verificarea de inchidere corecta e pe radacini. + +| Verificare | FUNDATIA | MASTERJOB | +|---|---|---| +| (a) total_d = prec_d+rulaj_d si total_c = prec_c+rulaj_c | 82/82 OK | 81/81 OK | +| (b) sold_d-sold_c = total_d-total_c | 82/82 OK | 81/81 OK | +| (c) frunze: suma sold_d = suma sold_c | 6 793 548.43 = 6 793 548.43, dif 0.00 **OK** | 2 112 044.07 vs 2 114 832.10, dif **-2 788.03 ESEC** | +| (c2) radacini: suma sold_d = suma sold_c | 6 053 716.76 = 6 053 716.76, dif 0.00 OK | 2 114 811.30 = 2 114 811.30, dif 0.00 OK | +| randul "Totaluri:" din PDF | 6 053 716.76 = 6 053 716.76 | 2 114 811.30 = 2 114 811.30 | +| cross-check "Total sume clasa N" = suma radacinilor clasei | 5/5 OK | 6/6 OK | +| (d) parinte vs analitice | 6 diferente pe laturi, 0 pe net | 9 diferente pe laturi, 2 pe net | + +Numerele de mai sus arata ca parsarea coordonatelor este corecta: (a) si (b) trec pentru +toate conturile, iar fiecare rand "Total sume clasa N" egaleaza exact suma radacinilor din +clasa respectiva (5/5 si 6/6), iar suma radacinilor egaleaza exact randul "Totaluri:". + +## Conturi problematice si explicatie + +Nu sunt erori de parsare; sunt doua comportamente reale SAGA: + +1. Netare D/C la sintetice (FUNDATIA `1171.01`): parintele este prezentat net, + copiii pe laturi. + - `prec_d`: parinte 629 448.54 vs copii 1 369 280.21 (dif -739 831.67) + - `prec_c`: parinte 0.00 vs copii 739 831.67 (dif -739 831.67) + - pe NET: parinte 773 608.10 = copii 773 608.10 -> 0 diferente pe net. + De aceea suma frunzelor (6 793 548.43) difera de "Totaluri" (6 053 716.76) cu exact + 739 831.67; inchiderea reala se face pe radacini si coincide cu PDF. + +2. Postari directe pe conturi sintetice (MASTERJOB): + - `117`: parinte 47 431.79 vs copii 44 795.92 -> diferenta 2 635.87 + - `5121`: parinte 15 730.61 vs copii net 15 578.45 -> diferenta 152.16 + Suma postarilor directe = 2 635.87 + 152.16 = **2 788.03**, exact deficitul de la + verificarea (c) pe frunze (sold_c - sold_d = 2 788.03). Frunzele nu contin aceste + postari, de aceea (c) pica; incluzandu-le (c2, radacini) balanta este inchisa si + coincide cu "Totaluri:" = 2 114 811.30. + +Concluzie: nu s-a ajustat nicio data. Verificarile (a), (b), (c2) si cross-check-ul pe +clase trec pentru ambele firme; (c) pe frunze pica doar la MASTERJOB din cauza postarilor +directe pe sintetice, dovedita prin relatia de mai sus. diff --git a/docs/verificare_FUNDATIA.md b/docs/verificare_FUNDATIA.md new file mode 100644 index 0000000..e0323eb --- /dev/null +++ b/docs/verificare_FUNDATIA.md @@ -0,0 +1,60 @@ +# Verificare `init_FUNDATIA_2025_12.xlsx` + +Generat de `genereaza_xlsx.py` din `balanta_FUNDATIA.csv`. Randuri de date: 75 (47 BALANTA, 28 FACTURA). + +## 1. Balanta generala (SUM totdeb = SUM totcred) + +- SUM(totdeb) = 7068369.5 +- SUM(totcred) = 7068369.5 +- diferenta (totdeb - totcred) = 0.0 -> OK +- Totaluri balanta: total_d=6328537.83 total_c=6328537.83 net=0.0 +- NET xlsx (0.0) vs NET Totaluri (0.0) -> OK +- Nota: SUM(totdeb)=7068369.5 difera de Totaluri.total_d=6328537.83 cu 739831.67; suma pe laturi a PDF-ului nu se poate reconstrui din frunze acolo unde SAGA a netat sinteticul (gross-ul parintelui e netat). Netul se pastreaza exact. + +## 2. Conturi frunza din CSV, reprezentate o singura data + +- frunze in CSV: 66 +- reprezentate in xlsx: 66 +- conturi pierdute: [] (gol) -> OK +- frunze cu mai putin/mai mult de un rand dedicat: [] (gol) -> OK + +## 3. Conturi partener: FACTURA + NEREPARTIZAT = net sintetic + +Formularul scade din randul BALANTA suma randurilor FACTURA de pe acelasi `(cont, acont, latura)` si lasa restul pe partenerul `NEREPARTIZAT`. Deci: `net sintetic - SUM(sold FACTURA cu semn) = analitice sarite + postare directa pe sintetic`. + +| cont | SUM(sold FACTURA) | net sintetic | analitice sarite | postare directa | NEREPARTIZAT asteptat | diferenta | rezultat | +|---|---|---|---|---|---|---|---| +| 401 | -314703.58 | -314703.58 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 4092 | 809.33 | 809.33 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 4111 | 15126.48 | 15126.48 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 4551 | -1571531.33 | -1571531.33 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 461 | 477938.37 | 477938.37 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 462 | -3400771.0 | -3400771.0 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 5121 | 81966.8 | 81966.8 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 5124 | 2492540.28 | 2492540.28 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 5311 | 72433.56 | 72433.56 | 0.0 | 0.0 | 0.0 | 0.0 | OK | + +Rezultat: OK + +## 4. Analitice sarite (sold pe latura opusa formularului) + +Latura FACTURA e fixa in cod (`:379`): `401,404,462,419,408,4551` -> CREDIT, orice alt cont -> DEBIT. Un analitic cu sold pe latura opusa nu primeste rand FACTURA; ramane in BALANTA si formularul ii pune `NEREPARTIZAT`. + +Niciunul. + +## 5. Lungimi si dubluri + +- cont > 4 sau acont > 4: [] (gol) -> OK +- perechi (cont, acont) duplicate la BALANTA: [] (gol) -> OK + +## 6. Randuri de diferenta generate (pct. 13-15) + +Niciunul (toate diferentele nete sunt zero). + +Nota: randurile FACTURA de tip `DIFERENTA SINTETIC` au fost eliminate; diferenta nu se mai inventa, o rezolva formularul prin `NEREPARTIZAT`. + +## Verdict + +TOATE verificarile au trecut. + +Nota: coloana `explicatia` (D/C la FACTURA) a fost folosita doar ca control intern si este goala in xlsx-ul final (capul de tabel o pastreaza). diff --git a/docs/verificare_MASTER.md b/docs/verificare_MASTER.md new file mode 100644 index 0000000..5f5b4d4 --- /dev/null +++ b/docs/verificare_MASTER.md @@ -0,0 +1,63 @@ +# Verificare `init_MASTER_2025_12.xlsx` + +Generat de `genereaza_xlsx.py` din `balanta_MASTERJOB.csv`. Randuri de date: 79 (46 BALANTA, 33 FACTURA). + +## 1. Balanta generala (SUM totdeb = SUM totcred) + +- SUM(totdeb) = 2318592.91 +- SUM(totcred) = 2318592.91 +- diferenta (totdeb - totcred) = 0.0 -> OK +- Totaluri balanta: total_d=2318572.11 total_c=2318572.11 net=0.0 +- NET xlsx (0.0) vs NET Totaluri (0.0) -> OK +- Nota: SUM(totdeb)=2318592.91 difera de Totaluri.total_d=2318572.11 cu 20.8; suma pe laturi a PDF-ului nu se poate reconstrui din frunze acolo unde SAGA a netat sinteticul (gross-ul parintelui e netat). Netul se pastreaza exact. + +## 2. Conturi frunza din CSV, reprezentate o singura data + +- frunze in CSV: 67 +- reprezentate in xlsx: 67 +- conturi pierdute: [] (gol) -> OK +- frunze cu mai putin/mai mult de un rand dedicat: [] (gol) -> OK + +## 3. Conturi partener: FACTURA + NEREPARTIZAT = net sintetic + +Formularul scade din randul BALANTA suma randurilor FACTURA de pe acelasi `(cont, acont, latura)` si lasa restul pe partenerul `NEREPARTIZAT`. Deci: `net sintetic - SUM(sold FACTURA cu semn) = analitice sarite + postare directa pe sintetic`. + +| cont | SUM(sold FACTURA) | net sintetic | analitice sarite | postare directa | NEREPARTIZAT asteptat | diferenta | rezultat | +|---|---|---|---|---|---|---|---| +| 401 | -547108.99 | -547108.99 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 4092 | 4.0 | 4.0 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 4111 | 12000.0 | 12000.0 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 4551 | -751724.61 | -751724.61 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 461 | 69289.0 | 69289.0 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 462 | -9810.0 | -9810.0 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 5121 | 15599.25 | 15730.61 | -20.8 | 152.16 | 131.36 | 131.36 | OK | +| 5124 | 1060090.96 | 1060090.96 | 0.0 | 0.0 | 0.0 | 0.0 | OK | +| 5311 | 98460.87 | 98460.87 | 0.0 | 0.0 | 0.0 | 0.0 | OK | + +Rezultat: OK + +## 4. Analitice sarite (sold pe latura opusa formularului) + +Latura FACTURA e fixa in cod (`:379`): `401,404,462,419,408,4551` -> CREDIT, orice alt cont -> DEBIT. Un analitic cu sold pe latura opusa nu primeste rand FACTURA; ramane in BALANTA si formularul ii pune `NEREPARTIZAT`. + +| cont | analitic | sold (semnat) | motiv | +|---|---|---|---| +| 5121 | 5121.01 | -20.8 | sold creditor vs latura D a formularului | + +## 5. Lungimi si dubluri + +- cont > 4 sau acont > 4: [] (gol) -> OK +- perechi (cont, acont) duplicate la BALANTA: [] (gol) -> OK + +## 6. Randuri de diferenta generate (pct. 13-15) + +- 117: diferenta neta 2635.87 -> BALANTA (analitic de diferenta) +- 5121: diferenta neta 152.16 -> BALANTA (analitic de diferenta, fara FACTURA) + +Nota: randurile FACTURA de tip `DIFERENTA SINTETIC` au fost eliminate; diferenta nu se mai inventa, o rezolva formularul prin `NEREPARTIZAT`. + +## Verdict + +TOATE verificarile au trecut. + +Nota: coloana `explicatia` (D/C la FACTURA) a fost folosita doar ca control intern si este goala in xlsx-ul final (capul de tabel o pastreaza). diff --git a/extract_balanta.py b/extract_balanta.py new file mode 100644 index 0000000..6a2d380 --- /dev/null +++ b/extract_balanta.py @@ -0,0 +1,243 @@ +"""Extractor fidel pentru balantele de verificare SAGA (PDF cu text). + +Foloseste pdfplumber cu coordonate (NU pdftotext -layout, care decaleaza coloanele). +Fiecare pagina are un antet cu 8 coloane numerice: + Sume precedente (D,C) | Rulaje perioada (D,C) | Sume totale (D,C) | Solduri finale (D,C) + +Utilizare: + py extract_balanta.py "" "" +""" + +import csv +import re +import sys + +import pdfplumber + +CONT_RE = re.compile(r"^\d+(?:\.\d+)*$") +NUM_RE = re.compile(r"^-?\d[\d.]*$") + +CONT_MAX_X = 80.0 +DENUM_MAX_X = 240.0 +ROW_TOL = 3.0 +TOL = 0.01 + +HEADER_WORDS = {"Cont", "Denumirea", "contului", "Debitoare", "Creditoare", + "Sume", "precedente", "Rulaje", "perioada", "totale", + "Solduri", "finale"} +TOTAL_WORDS = ("total", "totaluri") + + +def coloane_numerice(page0): + """Centrele celor 8 coloane, din etichetele Debitoare/Creditoare de pe pagina 1.""" + labels = [w for w in page0.extract_words() + if w["text"] in ("Debitoare", "Creditoare") and 75 <= w["top"] <= 100] + labels.sort(key=lambda w: w["x0"]) + assert len(labels) == 8, f"astept 8 etichete numerice, gasit {len(labels)}" + centre = [(w["x0"] + w["x1"]) / 2.0 for w in labels] + granite = [(centre[i] + centre[i + 1]) / 2.0 for i in range(len(centre) - 1)] + return centre, granite, max(w["top"] for w in labels) + + +def col_index(center, granite): + idx = 0 + for g in granite: + if center >= g: + idx += 1 + else: + break + return idx + + +def randuri(pagina): + """Grupeaza cuvintele in randuri dupa coordonata top (toleranta ROW_TOL).""" + words = sorted(pagina.extract_words(), key=lambda w: (w["top"], w["x0"])) + rows = [] + for w in words: + if rows and abs(w["top"] - rows[-1][0]) <= ROW_TOL: + rows[-1][1].append(w) + else: + rows.append((w["top"], [w])) + return rows + + +def numar(txt): + txt = txt.strip() + if txt in ("", "-", "."): + return 0.0 + return float(txt) + + +def parse_pdf(path): + conturi = [] + with pdfplumber.open(path) as pdf: + _, granite, header_top = coloane_numerice(pdf.pages[0]) + for pno, page in enumerate(pdf.pages, start=1): + for top, ws in randuri(page): + if top < header_top: + continue + cont = None + denum = [] + valori = [None] * 8 + for w in ws: + t = w["text"] + if t in HEADER_WORDS: + continue + if w["x0"] < CONT_MAX_X: + if CONT_RE.match(t): + cont = t + continue + if w["x0"] < DENUM_MAX_X: + denum.append(w) + continue + if NUM_RE.match(t): + ci = col_index((w["x0"] + w["x1"]) / 2.0, granite) + if valori[ci] is None: + valori[ci] = [] + valori[ci].append(w) + + denum = " ".join(w["text"] for w in sorted(denum, key=lambda x: x["x0"])) + vals = [] + for i in range(8): + if valori[i] is None: + vals.append(0.0) + else: + txt = "".join(x["text"] for x in + sorted(valori[i], key=lambda x: x["x0"])) + vals.append(numar(txt)) + + este_total = any(k in denum.lower() for k in TOTAL_WORDS) + if cont: + conturi.append({ + "pagina": pno, "cont": cont, "denumire": denum, + **dict(zip(("prec_d", "prec_c", "rulaj_d", "rulaj_c", + "total_d", "total_c", "sold_d", "sold_c"), vals)), + "este_total": 0, + }) + elif este_total: + conturi.append({ + "pagina": pno, "cont": "", "denumire": denum, + **dict(zip(("prec_d", "prec_c", "rulaj_d", "rulaj_c", + "total_d", "total_c", "sold_d", "sold_c"), vals)), + "este_total": 1, + }) + elif denum and conturi and conturi[-1]["este_total"] == 0: + # rand de continuare a denumirii contului precedent + conturi[-1]["denumire"] = (conturi[-1]["denumire"] + " " + denum).strip() + return conturi + + +NUMS = ["prec_d", "prec_c", "rulaj_d", "rulaj_c", + "total_d", "total_c", "sold_d", "sold_c"] + + +def verifica(rows): + reale = [r for r in rows if not r["este_total"]] + totaluri = [r for r in rows if r["este_total"]] + + a = b = 0 + for r in reale: + if abs(r["total_d"] - (r["prec_d"] + r["rulaj_d"])) > TOL or \ + abs(r["total_c"] - (r["prec_c"] + r["rulaj_c"])) > TOL: + a += 1 + if abs((r["sold_d"] - r["sold_c"]) - (r["total_d"] - r["total_c"])) > TOL: + b += 1 + + coduri = {r["cont"] for r in reale if r["cont"]} + copii = {} + for c in coduri: + parts = c.split(".") + if len(parts) > 1: + copii.setdefault(".".join(parts[:-1]), []).append(c) + + # frunza = nu apare ca parinte; radacina = parintele ei nu exista in balanta + frunze = [r for r in reale if r["cont"] not in copii] + radacini = [r for r in reale + if ".".join(r["cont"].split(".")[:-1]) not in coduri] + + fd = round(sum(r["sold_d"] for r in frunze), 2) + fc = round(sum(r["sold_c"] for r in frunze), 2) + rd = round(sum(r["sold_d"] for r in radacini), 2) + rc = round(sum(r["sold_c"] for r in radacini), 2) + + # (d) parinte vs suma analiticelor: pe fiecare latura si pe net (SAGA neteaza D/C) + byk = {r["cont"]: r for r in reale} + d_laturi = [] + d_net = [] + for r in reale: + kids = copii.get(r["cont"]) + if not kids: + continue + for col in NUMS: + s = round(sum(byk[k][col] for k in kids if k in byk), 2) + if abs(s - r[col]) > TOL: + d_laturi.append((r["cont"], col, r[col], s, round(r[col] - s, 2))) + pnet = round(r["sold_d"] - r["sold_c"], 2) + cnet = round(sum(byk[k]["sold_d"] - byk[k]["sold_c"] + for k in kids if k in byk), 2) + if abs(pnet - cnet) > TOL: + d_net.append((r["cont"], pnet, cnet, round(pnet - cnet, 2))) + + # cross-check parser: fiecare "Total sume clasa N" = suma radacinilor din clasa + clase_ok = clase_rau = 0 + clase_det = [] + for t in totaluri: + if "clasa" not in t["denumire"].lower(): + continue + cl = t["denumire"].split()[-1] + top = [r for r in radacini if r["cont"].startswith(cl)] + sd = round(sum(r["sold_d"] for r in top), 2) + sc = round(sum(r["sold_c"] for r in top), 2) + ok = abs(sd - t["sold_d"]) <= TOL and abs(sc - t["sold_c"]) <= TOL + if ok: + clase_ok += 1 + else: + clase_rau += 1 + clase_det.append((cl, t["sold_d"], sd, t["sold_c"], sc)) + tot_row = [t for t in totaluri if "totaluri" in t["denumire"].lower()] + + print("=== VERIFICARE ===") + print(f"randuri conturi reale : {len(reale)}") + print(f"conturi frunza : {len(frunze)} conturi radacina: {len(radacini)}") + print(f"(a) total=prec+rulaj : {len(reale) - a}/{len(reale)} OK, {a} esec") + print(f"(b) sold=total : {len(reale) - b}/{len(reale)} OK, {b} esec") + print(f"(c) balanta frunze : sold_d={fd} sold_c={fc} " + f"diferenta={round(fd - fc, 2)} {'OK' if abs(fd - fc) <= TOL else 'ESEC'}") + print(f"(c2) balanta radacini : sold_d={rd} sold_c={rc} " + f"diferenta={round(rd - rc, 2)} {'OK' if abs(rd - rc) <= TOL else 'ESEC'}") + if tot_row: + tr = tot_row[0] + print(f" Totaluri (PDF) : sold_d={tr['sold_d']} sold_c={tr['sold_c']}") + print(f" cross-check clase: {clase_ok} OK, {clase_rau} esec") + print(f"(d) parinti vs analitice: {len(d_laturi)} diferente pe laturi, " + f"{len(d_net)} diferente pe net") + for p in d_laturi: + print(" d-latura", p) + for p in d_net: + print(" d-NET ", p) + for p in clase_det: + print(" clasa ", p) + return {"n": len(reale), "frunze": len(frunze), "radacini": len(radacini), + "a": a, "b": b, "fd": fd, "fc": fc, "rd": rd, "rc": rc, + "d_laturi": d_laturi, "d_net": d_net, "clase_det": clase_det, + "totaluri": [(t["sold_d"], t["sold_c"]) for t in tot_row]} + + +def main(): + if len(sys.argv) != 3: + print(__doc__) + sys.exit(1) + pdf_path, csv_path = sys.argv[1], sys.argv[2] + rows = parse_pdf(pdf_path) + cols = ["pagina", "cont", "denumire"] + NUMS + ["este_total"] + with open(csv_path, "w", newline="", encoding="utf-8-sig") as f: + wr = csv.DictWriter(f, fieldnames=cols) + wr.writeheader() + for r in rows: + wr.writerow(r) + print(f"scris {csv_path}: {len(rows)} randuri") + verifica(rows) + + +if __name__ == "__main__": + main() diff --git a/genereaza_xlsx.py b/genereaza_xlsx.py new file mode 100644 index 0000000..355d3b3 --- /dev/null +++ b/genereaza_xlsx.py @@ -0,0 +1,490 @@ +"""Genereaza fisierele xlsx de initializare ROACONT din balantele SAGA (CSV). + +Produce (pentru fiecare firma): + init__2025_12.xlsx - un sheet, randul 1 = capul de tabel, + datele de la randul 2 in jos + docs/verificare_.md - verificarile obligatorii + +Reguli: docs/decizii_import.md (pct. 11-15) si docs/conturi_cu_analitice.md. + +Forma randurilor (revizuit 20.09.2026, vezi pct. 14-15): +- cont obisnuit: doar BALANTA per frunza (acont completat). +- 401/4092/4111/461/462/4551: un BALANTA agregat pe sintetic (acont gol) + cate + un FACTURA per analitic (acont gol). +- 5121/5124: analiticele raman analitice; per analitic un BALANTA cu acont SI un + FACTURA cu ACELASI acont. +- 5311: BALANTA + FACTURA pe sintetic (acont gol), partener CENTRALA. +- 5125: cont obisnuit cu analitice (fara parteneri). +- diferenta neta parinte/copii (postare directa pe sintetic): la nepartener si la + 5121/5124 devine rand BALANTA de diferenta (analitic nou, fara FACTURA); la + ceilalti parteneri se include in BALANTA agregat. NU se mai emite FACTURA de + diferenta (o rezolva formularul, prin NEREPARTIZAT). +- analiticul cu sold pe latura opusa celei fixate de formular (':379') nu primeste + FACTURA; ramane doar in BALANTA si apare ca NEREPARTIZAT. +""" + +import csv +import os + +from openpyxl import load_workbook + +AN = 2025 +LUNA = 12 +DATA = "01.12.2025" +DATASCAD = "31.12.2025" +SERIE = None +VALUTA = None + +TEMPLATE = "init_facturi_balanta_note.xlsx" + +# Latura pe care formularul pune randurile FACTURA (frm...sc2:379/'383'): +# conturile din lista merg pe CREDIT, tot restul pe DEBIT. +LATURA_CREDIT = {"401", "404", "462", "419", "408", "4551"} + +# 5121/5124: analiticele raman analitice SI primesc partener (BALANTA + FACTURA +# pe acelasi acont). +PARTENER_BANCA = {"5121", "5124"} +# Conturi cu parteneri, un singur BALANTA agregat pe sintetic + FACTURA per analitic. +PARTENER_SINTETIC = {"401", "4092", "4111", "461", "462", "4551"} +# Casa: fara analitice, BALANTA + FACTURA pe sintetic. +PARTENER_FARA_ANALITICE = {"5311"} + +PARTENER = PARTENER_BANCA | PARTENER_SINTETIC | PARTENER_FARA_ANALITICE + +FIRME = [ + ("FUNDATIA", "balanta_FUNDATIA.csv"), + ("MASTER", "balanta_MASTERJOB.csv"), +] + + +class Stop(Exception): + """Conditie neprevazuta: nu ghicim, raportam.""" + + +def citeste_header(): + wb = load_workbook(TEMPLATE, read_only=True) + ws = wb.active + hdr = [c.value for c in ws[1]] + wb.close() + return hdr + + +def citeste_balanta(path): + rows = [] + with open(path, encoding="utf-8-sig", newline="") as f: + for r in csv.DictReader(f): + cont = (r["cont"] or "").strip() + if r["este_total"] == "1" or cont == "": + continue + rows.append({ + "cont": cont, + "denumire": (r["denumire"] or "").strip(), + "total_d": float(r["total_d"]), + "total_c": float(r["total_c"]), + }) + return rows + + +def citeste_totaluri(path): + with open(path, encoding="utf-8-sig", newline="") as f: + for r in csv.DictReader(f): + if "totaluri" in (r["denumire"] or "").lower(): + return float(r["total_d"]), float(r["total_c"]) + return None + + +def arbore(rows): + by = {r["cont"]: r for r in rows} + children = {} + for c in by: + p = ".".join(c.split(".")[:-1]) + if p in by: + children.setdefault(p, []).append(c) + return by, children + + +def este_partener(cont): + return cont.split(".")[0] in PARTENER + + +def latura_factura(cont): + """Latura fixa pe care formularul pune randurile FACTURA ale contului.""" + return "C" if cont.split(".")[0] in LATURA_CREDIT else "D" + + +def split_cont(cont): + seg = cont.split(".") + return seg[0], "".join(seg[1:]) + + +def diferente(by, children): + """(cont_parinte, diferenta_net) pentru parintii cu postare directa.""" + out = [] + for cont, r in by.items(): + kids = children.get(cont) + if not kids: + continue + pnet = round(r["total_d"] - r["total_c"], 2) + cnet = round(sum(by[k]["total_d"] - by[k]["total_c"] for k in kids), 2) + d = round(pnet - cnet, 2) + if abs(d) > 0.005: + out.append((cont, d)) + return out + + +def acont_diferenta(parent, kids): + """Primul cod liber de forma 99 (segmente scurte) / 9999 (segmente lungi).""" + seg = parent.split(".") + base = "".join(seg[1:]) + style = 2 if max(len(k.split(".")[-1]) for k in kids) <= 2 else 4 + cod = "99" if style == 2 else "9999" + ac = base + cod + if len(ac) > 4: + raise Stop(f"acont diferenta prea lung pentru {parent}: '{ac}'") + frati = {split_cont(k)[1] for k in kids} + if ac in frati: + raise Stop(f"acont diferenta '{ac}' deja folosit sub {parent}") + return ac + + +def rand(header, **kw): + r = {h: None for h in header} + r.update(an=AN, luna=LUNA, data=DATA, datascad=DATASCAD, + serie=SERIE, valuta=VALUTA) + r.update(kw) + return r + + +def _semn_sold(net): + return "creditor" if net < 0 else "debitor" + + +def genereaza(rows, header): + by, children = arbore(rows) + diffs = diferente(by, children) + diff_by_parent = dict(diffs) + + # verificarile de structura care nu se ghicesc + for cont in by: + if este_partener(cont): + continue + if cont not in children: + cont4, ac = split_cont(cont) + if len(cont4) > 4 or len(ac) > 4: + raise Stop(f"cont/acont prea lung: {cont} -> ({cont4},{ac})") + for parent in diff_by_parent: + if not este_partener(parent) or parent.split(".")[0] in PARTENER_BANCA: + acont_diferenta(parent, children[parent]) + for p in {c.split(".")[0] for c in by if este_partener(c)}: + for k in children.get(p, []): + if k in children: + raise Stop(f"analitic partener cu sub-analitice: {k}") + + out = [] + leaf_map = {} # frunza -> randurile dedicate (folosite la dubluri) + leaf_rep = set() # toate frunzele reprezentate (inclusiv in BALANTA agregat) + sarite = [] # (cont, analitic, sold_semnat, motiv) + + def add(r, leaf=None): + out.append(r) + if leaf is not None: + leaf_map.setdefault(leaf, []).append(len(out) - 1) + leaf_rep.add(leaf) + + # A. conturi nepartener: cate un BALANTA per frunza + for r in rows: + if este_partener(r["cont"]) or r["cont"] in children: + continue + cont4, ac = split_cont(r["cont"]) + add(rand(header, TIP="BALANTA", cont=cont4, acont=ac, numar=1, + nume=r["denumire"], totdeb=round(r["total_d"], 2), + totcred=round(r["total_c"], 2)), leaf=r["cont"]) + + # A. analitic de diferenta pe parinte nepartener (postare directa pe sintetic) + for cont, d in diffs: + if este_partener(cont): + continue + ac = acont_diferenta(cont, children[cont]) + add(rand(header, TIP="BALANTA", cont=cont.split(".")[0], acont=ac, + numar=1, nume="DIFERENTA SINTETIC SAGA", + totdeb=d if d > 0 else None, + totcred=-d if d < 0 else None)) + + parteneri = sorted({c.split(".")[0] for c in by if este_partener(c)}) + for p in parteneri: + direct = children.get(p, []) + side = latura_factura(p) + + if p in PARTENER_BANCA and direct: + # 5121/5124: BALANTA cu acont + FACTURA cu ACELASI acont. + for k in direct: + kd = by[k] + kac = split_cont(k)[1] + add(rand(header, TIP="BALANTA", cont=p, acont=kac, numar=1, + nume=kd["denumire"], totdeb=round(kd["total_d"], 2), + totcred=round(kd["total_c"], 2)), leaf=k) + net = round(kd["total_d"] - kd["total_c"], 2) + if net == 0: + continue + if (net > 0) == (side == "D"): + add(rand(header, TIP="FACTURA", cont=p, acont=kac, + numar=k.replace(".", ""), + nume=kd["denumire"] or f"FURNIZOR {k}", + cod_fiscal=k, sold=abs(net), explicatia=side)) + else: + sarite.append((p, k, net, + f"sold {_semn_sold(net)} vs latura {side} " + f"a formularului")) + if p in diff_by_parent: + d = diff_by_parent[p] + ac = acont_diferenta(p, direct) + add(rand(header, TIP="BALANTA", cont=p, acont=ac, numar=1, + nume="DIFERENTA SINTETIC SAGA", + totdeb=d if d > 0 else None, + totcred=-d if d < 0 else None)) + continue + + # 401/4092/4111/461/462/4551 si 5311 + if direct: + base_d = sum(by[k]["total_d"] for k in direct) + base_c = sum(by[k]["total_c"] for k in direct) + d = diff_by_parent.get(p, 0.0) + add(rand(header, TIP="BALANTA", cont=p, acont=None, numar=1, + nume=by[p]["denumire"], + totdeb=round(base_d + (d if d > 0 else 0.0), 2), + totcred=round(base_c + (-d if d < 0 else 0.0), 2))) + for k in direct: + net = round(by[k]["total_d"] - by[k]["total_c"], 2) + if net == 0: + leaf_rep.add(k) + continue + if (net > 0) == (side == "D"): + add(rand(header, TIP="FACTURA", cont=p, acont=None, + numar=k.replace(".", ""), + nume=by[k]["denumire"] or f"FURNIZOR {k}", + cod_fiscal=k, sold=abs(net), explicatia=side), + leaf=k) + else: + sarite.append((p, k, net, + f"sold {_semn_sold(net)} vs latura {side} " + f"a formularului")) + leaf_rep.add(k) + else: + net = round(by[p]["total_d"] - by[p]["total_c"], 2) + add(rand(header, TIP="BALANTA", cont=p, acont=None, numar=1, + nume=by[p]["denumire"], totdeb=round(by[p]["total_d"], 2), + totcred=round(by[p]["total_c"], 2)), leaf=p) + if net != 0: + if (net > 0) == (side == "D"): + nume = "CENTRALA" if p == "5311" else by[p]["denumire"] + add(rand(header, TIP="FACTURA", cont=p, acont=None, + numar=p, nume=nume, cod_fiscal=p, sold=abs(net), + explicatia=side)) + else: + sarite.append((p, p, net, + f"sold {_semn_sold(net)} vs latura {side} " + f"a formularului")) + return out, diffs, leaf_map, leaf_rep, sarite + + +def scrie_xlsx(header, rows, path): + wb = load_workbook(TEMPLATE) + ws = wb.active + if ws.max_row > 1: + ws.delete_rows(2, ws.max_row - 1) + for i, r in enumerate(rows, start=2): + for j, h in enumerate(header, start=1): + v = r.get(h) + if h == "explicatia": # coloana temporara de control + v = None + ws.cell(i, j, v) + wb.save(path) + + +def verifica(firma, csv_path, xlsx_path, rows, out, diffs, leaf_map, leaf_rep, + sarite, header): + by, children = arbore(rows) + leaves = [c for c in by if c not in children] + diff_by_parent = dict(diffs) + + totdeb = round(sum(r["totdeb"] or 0 for r in out), 2) + totcred = round(sum(r["totcred"] or 0 for r in out), 2) + net = round(totdeb - totcred, 2) + toturi = citeste_totaluri(csv_path) + + pierdute = sorted(set(leaves) - leaf_rep) + duplicate_leaf = sorted(c for c, v in leaf_map.items() if len(v) != 1) + + # lungimi + dubluri (cont,acont) pe BALANTA + lungimi = [] + bal_pairs = {} + for r in out: + if len(r["cont"]) > 4: + lungimi.append(("cont", r["cont"])) + if r["acont"] and len(r["acont"]) > 4: + lungimi.append(("acont", r["acont"])) + if r["TIP"] == "BALANTA": + bal_pairs.setdefault((r["cont"], r["acont"]), []).append(r) + dubluri_bal = {k: v for k, v in bal_pairs.items() if len(v) > 1} + + # parteneri: SUM(sold FACTURA cu semn) + NEREPARTIZAT asteptat = net sintetic + part_rows = {} + for r in out: + if r["TIP"] == "FACTURA": + semn = 1 if latura_factura(r["cont"]) == "D" else -1 + part_rows[r["cont"]] = part_rows.get(r["cont"], 0.0) + semn * (r["sold"] or 0) + + sarite_by_cont = {} + for cont, _k, s, _motiv in sarite: + sarite_by_cont[cont] = round(sarite_by_cont.get(cont, 0.0) + s, 2) + + part_verif = [] + for p in sorted({c.split(".")[0] for c in by if este_partener(c)}): + net_sint = round(by[p]["total_d"] - by[p]["total_c"], 2) + suma = round(part_rows.get(p, 0.0), 2) + sarit = round(sarite_by_cont.get(p, 0.0), 2) + direct = round(diff_by_parent.get(p, 0.0), 2) + asteptat = round(sarit + direct, 2) + diferenta = round(net_sint - suma, 2) + ok = abs(diferenta - asteptat) <= 0.005 + part_verif.append((p, suma, net_sint, sarit, direct, asteptat, diferenta, ok)) + + ok_bal = abs(net) <= 0.005 + ok_leaves = not pierdute and not duplicate_leaf + ok_part = all(x[7] for x in part_verif) + ok_lung = not lungimi and not dubluri_bal + + L = [] + L.append(f"# Verificare `{os.path.basename(xlsx_path)}`") + L.append("") + L.append(f"Generat de `genereaza_xlsx.py` din `{os.path.basename(csv_path)}`. " + f"Randuri de date: {len(out)} ({sum(1 for r in out if r['TIP']=='BALANTA')} BALANTA, " + f"{sum(1 for r in out if r['TIP']=='FACTURA')} FACTURA).") + L.append("") + L.append("## 1. Balanta generala (SUM totdeb = SUM totcred)") + L.append("") + L.append(f"- SUM(totdeb) = {totdeb}") + L.append(f"- SUM(totcred) = {totcred}") + L.append(f"- diferenta (totdeb - totcred) = {net} -> {'OK' if ok_bal else '**ESEC**'}") + if toturi: + td, tc = toturi + L.append(f"- Totaluri balanta: total_d={td} total_c={tc} " + f"net={round(td - tc, 2)}") + L.append(f"- NET xlsx ({net}) vs NET Totaluri ({round(td - tc, 2)}) -> " + f"{'OK' if abs(net - (td - tc)) <= 0.005 else '**ESEC**'}") + L.append(f"- Nota: SUM(totdeb)={totdeb} difera de Totaluri.total_d={td} cu " + f"{round(totdeb - td, 2)}; suma pe laturi a PDF-ului nu se poate " + f"reconstrui din frunze acolo unde SAGA a netat sinteticul (gross-ul " + f"parintelui e netat). Netul se pastreaza exact.") + L.append("") + L.append("## 2. Conturi frunza din CSV, reprezentate o singura data") + L.append("") + L.append(f"- frunze in CSV: {len(leaves)}") + L.append(f"- reprezentate in xlsx: {len(leaf_rep)}") + L.append(f"- conturi pierdute: {pierdute if pierdute else '[] (gol)'} -> " + f"{'OK' if not pierdute else '**ESEC**'}") + L.append(f"- frunze cu mai putin/mai mult de un rand dedicat: " + f"{duplicate_leaf if duplicate_leaf else '[] (gol)'} -> " + f"{'OK' if not duplicate_leaf else '**ESEC**'}") + L.append("") + L.append("## 3. Conturi partener: FACTURA + NEREPARTIZAT = net sintetic") + L.append("") + L.append("Formularul scade din randul BALANTA suma randurilor FACTURA de pe " + "acelasi `(cont, acont, latura)` si lasa restul pe partenerul " + "`NEREPARTIZAT`. Deci: `net sintetic - SUM(sold FACTURA cu semn) = " + "analitice sarite + postare directa pe sintetic`.") + L.append("") + L.append("| cont | SUM(sold FACTURA) | net sintetic | analitice sarite | postare directa | NEREPARTIZAT asteptat | diferenta | rezultat |") + L.append("|---|---|---|---|---|---|---|---|") + for p, suma, net_sint, sarit, direct, asteptat, diferenta, ok in part_verif: + L.append(f"| {p} | {suma} | {net_sint} | {sarit} | {direct} | {asteptat} " + f"| {diferenta} | {'OK' if ok else '**ESEC**'} |") + L.append("") + L.append(f"Rezultat: {'OK' if ok_part else '**ESEC**'}") + L.append("") + L.append("## 4. Analitice sarite (sold pe latura opusa formularului)") + L.append("") + L.append("Latura FACTURA e fixa in cod (`:379`): `401,404,462,419,408,4551` -> " + "CREDIT, orice alt cont -> DEBIT. Un analitic cu sold pe latura opusa nu " + "primeste rand FACTURA; ramane in BALANTA si formularul ii pune " + "`NEREPARTIZAT`.") + L.append("") + if not sarite: + L.append("Niciunul.") + else: + L.append("| cont | analitic | sold (semnat) | motiv |") + L.append("|---|---|---|---|") + for cont, k, s, motiv in sarite: + L.append(f"| {cont} | {k} | {s} | {motiv} |") + L.append("") + L.append("## 5. Lungimi si dubluri") + L.append("") + L.append(f"- cont > 4 sau acont > 4: {lungimi if lungimi else '[] (gol)'} -> " + f"{'OK' if not lungimi else '**ESEC**'}") + L.append(f"- perechi (cont, acont) duplicate la BALANTA: " + f"{list(dubluri_bal) if dubluri_bal else '[] (gol)'} -> " + f"{'OK' if not dubluri_bal else '**ESEC**'}") + L.append("") + L.append("## 6. Randuri de diferenta generate (pct. 13-15)") + L.append("") + if not diffs: + L.append("Niciunul (toate diferentele nete sunt zero).") + for cont, d in diffs: + base = cont.split(".")[0] + if base in PARTENER_BANCA: + kind = "BALANTA (analitic de diferenta, fara FACTURA)" + elif este_partener(cont): + kind = "inclus in BALANTA agregat al sinteticului (fara FACTURA)" + else: + kind = "BALANTA (analitic de diferenta)" + L.append(f"- {cont}: diferenta neta {d} -> {kind}") + L.append("") + L.append("Nota: randurile FACTURA de tip `DIFERENTA SINTETIC` au fost eliminate; " + "diferenta nu se mai inventa, o rezolva formularul prin `NEREPARTIZAT`.") + L.append("") + L.append("## Verdict") + L.append("") + toate = ok_bal and ok_leaves and ok_part and ok_lung + L.append(f"{'TOATE verificarile au trecut.' if toate else '**UNA SAU MAI MULTE VERIFICARI AU PICAT - datele NU au fost ajustate.**'}") + L.append("") + L.append("Nota: coloana `explicatia` (D/C la FACTURA) a fost folosita doar ca " + "control intern si este goala in xlsx-ul final (capul de tabel o pastreaza).") + L.append("") + + with open(os.path.join("docs", f"verificare_{firma}.md"), "w", + encoding="utf-8") as f: + f.write("\n".join(L)) + + return {"bal": ok_bal, "leaves": ok_leaves, "part": ok_part, "lung": ok_lung, + "totdeb": totdeb, "totcred": totcred, "net": net, + "pierdute": pierdute, "dubluri_leaf": duplicate_leaf, + "dubluri_bal": list(dubluri_bal), "lungimi": lungimi, + "part_verif": part_verif, "sarite": sarite} + + +def main(): + header = citeste_header() + assert len(header) == 39, f"cap de tabel neasteptat: {len(header)} coloane" + for firma, csv_path in FIRME: + rows = citeste_balanta(csv_path) + out, diffs, leaf_map, leaf_rep, sarite = genereaza(rows, header) + xlsx_path = f"init_{firma}_2025_12.xlsx" + scrie_xlsx(header, out, xlsx_path) + rez = verifica(firma, csv_path, xlsx_path, rows, out, diffs, leaf_map, + leaf_rep, sarite, header) + print(f"=== {firma} ===") + print(f" rows: {len(out)} totdeb={rez['totdeb']} totcred={rez['totcred']} net={rez['net']}") + print(f" balanta={'OK' if rez['bal'] else 'ESEC'} " + f"frunze={'OK' if rez['leaves'] else 'ESEC'} " + f"parteneri={'OK' if rez['part'] else 'ESEC'} " + f"lungimi={'OK' if rez['lung'] else 'ESEC'}") + print(f" scris {xlsx_path} si docs/verificare_{firma}.md") + if rez["sarite"]: + print(f" analitice sarite: {rez['sarite']}") + if rez["pierdute"] or rez["dubluri_leaf"] or rez["dubluri_bal"] or rez["lungimi"]: + print(" ATENTIE:", rez["pierdute"], rez["dubluri_leaf"], + rez["dubluri_bal"], rez["lungimi"]) + + +if __name__ == "__main__": + main() diff --git a/init_FUNDATIA_2025_12.xlsx b/init_FUNDATIA_2025_12.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..7a4555b213d960ea252dfbf731fcb4433e90a333 GIT binary patch literal 11192 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 literal 0 HcmV?d00001