# 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`.