Files
solduri2roa/docs/raport_form_init_balanta.md
Marius Mutu 92dc8c7b32 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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BdA5a3ECKFD6Citf1ptPZu
2026-09-21 00:02:30 +03:00

13 KiB

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.