Compare commits

..

4 Commits

Author SHA1 Message Date
1f43c29955 Tranzit: repartitie proportionala valoare finala cand coeficientul de distanta e 0
Precizia coeficientului de distanta revine la 2 zecimale (gnProcDistPrecizie=2)
pentru compatibilitate cu facturile/stornarile anterioare. Cand procdist se
rotunjeste la 0 (distante scurte) si se introduce o valoare finala manuala,
aceasta se repartizeaza proportional pe nave dupa baza fara coeficient de
distanta (tarif * cant * (corect + procdiv)), la facturare si la stornare.
Cantitatea de stornare se recalculeaza proportional, nu mai devine 0.

Bump versiune 2.0.5 -> 2.0.6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 14:34:11 +03:00
69c5290a8d Calcul tranzit: coeficient distanta rotunjit la 3 zecimale + protectie impartire la 0
Pentru distante scurte (ex. 0.2 km) coeficientul de distanta rotunjit la 2
zecimale iesea 0, deci valoarea facturata era 0. Rotunjire la 3 zecimale in
do_executa si in afisarea "mod de calcul". Protectie la impartirea cu 0 la
valoarea finala cand valoarea convoiului calculat este 0.

Adauga docs/fluxuri_calcul_facturare.md (lant facturare end-to-end pe tipuri)
si referinta in CLAUDE.md. Changelog 2.0.5.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 13:45:20 +03:00
d9bf25016f foxbin2prg 2026-06-15 12:50:06 +03:00
189ee3b000 init 2026-06-15 12:16:42 +03:00
28 changed files with 529 additions and 18 deletions

13
.gitignore vendored
View File

@@ -7,19 +7,6 @@
*.BAK
*.TBK
# Visual FoxPro - fisiere memo pereche (binare generate automat)
*.pjt
*.PJT
*.sct
*.SCT
*.vct
*.VCT
*.frt
*.FRT
*.lbt
*.LBT
*.mnt
*.MNT
# Visual FoxPro - meniuri generate (din .mnx)
*.mpr

View File

@@ -29,6 +29,25 @@ user-facing strings, comments, and changelog entries.
- The compiler error log is `roaacnpro.ERR`; the runtime log is `log.txt`. Many entries in
`roaacnpro.ERR` are benign cross-references resolved at runtime from `COMUN` libraries.
## Searching code inside `.vcx`/`.scx` (binary) libraries
Most class/form code lives **inside binaries** (`.vcx`+`.vct`, `.scx`+`.sct`, …), not in `.prg`,
so plain grep can't read it cleanly. To search method/procedure bodies, convert the binaries to
their TEXT form first and grep the text. **At the start of a session (when work may touch
classes/forms), refresh the text cache** by running the helper, then search in the cache:
```powershell
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 # incremental
```
By default it is **project-driven**: it reads `roaacnpro.PJX` and converts only the `.vcx`/`.scx`
the project actually uses (~78 files), **not** all of `COMUN\` (most of which is unused). It writes
a mirrored, read-only text tree to `D:\ROA\UTIL\foxbin2prg\_textcache\`
(e.g. `_textcache\Clase\oacnpro.vc2`, `_textcache\comun\clase\_frm_base.vc2`); then `Grep` there.
Useful flags: `-Types vcx,scx,frx,mnx` (also reports/menus), `-Source <file|folder>` (one-off,
even outside the project), `-Force`, `-Clean`. The text is **only for reading/search** — edit code
in the VFP IDE. Full guide: **`docs/cautare_vcx_vct.md`**.
## The COMUN shared framework
`COMUN/` (and the sibling `..\COMUNROA\`) is **shared, framework-level code used by every ROA
@@ -101,6 +120,12 @@ throughout the codebase:
the `crsFactura` structure, the VAT formulas, and which files to touch for a given task. Key
rule: `PACK_FACTURARE.pck` is the source of truth; the `frm_factura` preview must mirror its
formulas, and reports/list only read package-computed values.
- **`docs/fluxuri_calcul_facturare.md`** — the end-to-end billing chain (Import → Calcul →
Salvare → Listare) documented per service type (tranzit, cheiaj, chirii, penalități, apă,
diverse): where source data is imported from (RORIS/`ips_*`), the exact value/coefficient
formulas and roundings, where results are persisted, and what reports/recapitulations read
back. Read this to find which file:line computes a given value. Includes a "Capcane cunoscute"
section (e.g. the distance-coefficient rounding that zeroes sub-32m distances).
- **`Programe/proceduri_acnpro_rapoarte.prg`** — report-generation procedures feeding the
`Rapoarte/*.frx` layouts (factura, recapitulatie_cheiaj/tranzit/penalitati, registru tranzit).
- **`Programe/importroris*.prg`** + `importroris.pjx` — a *separate* small executable

BIN
Clase/oacnpro.VCT Normal file

Binary file not shown.

Binary file not shown.

BIN
Clase/ofundal_facturare.vct Normal file

Binary file not shown.

BIN
Ferestre/fundal.SCT Normal file

Binary file not shown.

BIN
Ferestre/importroris.SCT Normal file

Binary file not shown.

BIN
Meniuri/roaacnpro.MNT Normal file

Binary file not shown.

Binary file not shown.

BIN
Meniuri/tarife.MNT Normal file

Binary file not shown.

View File

@@ -1 +1,3 @@
**OVARIABILE_GLOBALE.PRG
**OVARIABILE_GLOBALE.PRG
PUBLIC gnProcDistPrecizie
gnProcDistPrecizie = 2 && precizie zecimale rotunjire calcul si afisare procent distanta parcursa / lungime CDMN 64.4 km

View File

@@ -5743,7 +5743,7 @@ Procedure mod_calcul_tranzit
Select vye_id, intern, indicativ, tarif, valuta, cant, um, procdist, corect, procdiv, valval, Curs, valftva From (m.tcTabel) Where vye_id = m.tcVyeId Order By indicativ Into Cursor cModCalculTemp
Select cModCalculTemp
Scan
lcModCalcul = lcModCalcul + Alltrim(Transform(tarif, GET_MASK(10, 4))) + [ ] + Allt(valuta) + [ * ] + Allt(Str(cant, 8, 2)) + [ ] + Allt(um) + [ * ] + Allt(Str(procdist, 6, 2)) + [ * ] + Allt(Str(corect + procdiv, 5, 2)) + [ = ] + Alltrim(Transform(valval, GET_MASK(16, 2))) + [ ] + Allt(valuta)
lcModCalcul = lcModCalcul + Alltrim(Transform(tarif, GET_MASK(10, 4))) + [ ] + Allt(valuta) + [ * ] + Allt(Str(cant, 8, 2)) + [ ] + Allt(um) + [ * ] + Allt(Str(procdist, 6, m.gnProcDistPrecizie)) + [ * ] + Allt(Str(corect + procdiv, 5, 3)) + [ = ] + Alltrim(Transform(valval, GET_MASK(16, 2))) + [ ] + Allt(valuta)
llIntern = intern
lnCurs = Curs
If m.llIntern

BIN
Rapoarte/factura_acn.FRT Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Rapoarte/sit_cheiaj4.FRT Normal file

Binary file not shown.

BIN
Rapoarte/sit_cheiaj5.FRT Normal file

Binary file not shown.

BIN
Rapoarte/sit_tranzit3.FRT Normal file

Binary file not shown.

View File

@@ -1,11 +1,27 @@
<!--
17/06/2026
ROAACNPRO - 2.0.6
:modificare:
Calcul tranzit. Precizia coeficientului de distanta a revenit la 2 zecimale, pentru ca facturile si stornarile sa fie calculate identic cu cele anterioare.
Cand coeficientul de distanta se rotunjeste la 0 (distante scurte, ex 0.2 km) si se introduce o valoare finala manuala, aceasta se repartizeaza acum proportional pe nave dupa baza fara coeficient de distanta (tarif * cant * (corect + procdiv)), atat la facturare cat si la stornare.
Cantitatea de stornare se recalculeaza proportional, nu mai devine 0.
-->
<!--
15/06/2026
ROAACNPRO - 2.0.5
:modificare:
Modificare calcul tranzit coeficient distanta rotunjit la 3 zecimale. Pentru distante scurte (ex 0.2 km) coeficientul de distanta rotunjit la 2 zecimale era 0 si valoarea facturata era 0.
-->
<!--
10/06/2026
ROAACNPRO - 2.0.4
:nou:
Facturare cu pret inclusiv TVA. Pe randurile de factura cu "Pret cu TVA" bifat, valorile se
calculeaza invers (se extrage TVA din pretul brut), sincronizat cu calculul din PACK_FACTURARE,
cu relistarea facturii si cu lista de facturi.
Facturare cu pret inclusiv TVA. Pe randurile de factura cu "Pret cu TVA" bifat, valorile se calculeaza invers (se extrage TVA din pretul brut).
-->
<!--

122
docs/cautare_vcx_vct.md Normal file
View File

@@ -0,0 +1,122 @@
# Căutare în codul din librăriile/formele VFP (`.vcx`/`.vct`, `.scx`/`.sct`, ...)
Cum se caută cod-sursă (proceduri, metode, parametri) care **nu** stă în fișiere `.prg`, ci
în interiorul fișierelor binare VFP: librării de clase (`.vcx`+`.vct`), forme (`.scx`+`.sct`),
rapoarte (`.frx`+`.frt`), meniuri (`.mnx`+`.mnt`), baze de date (`.dbc`+`.dct`).
## De ce e nevoie de asta
Un `.vcx` este de fapt o **tabelă DBF**: codul metodelor stă în câmpuri memo în `.vct`. Un
`grep` direct pe `.vct` *găsește* textul, dar îl vede ca fișier binar (octeți `\0` între linii),
fără numere de linie utile și greu de citit. Soluția: convertim binarul în reprezentarea lui
**TEXT** (`.vc2`, `.sc2`, …) — un PRG-style lizibil, cu metode sortate alfabetic — și căutăm
în text cu `grep`/`Grep`.
> **Regula de aur:** textul generat e **doar pentru citire/căutare**. Modificările de cod se fac
> tot în **IDE-ul VFP** (vezi `CLAUDE.md`). Nu edita `.vcx/.vct` pe text și nu pune textul înapoi
> în binar pentru aceste scopuri.
## Unelte disponibile (verificate)
| Unealtă | Cale | Rol | Recomandare |
|---|---|---|---|
| **FoxBin2Prg** | `D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE` | Binar VFP ⇄ text bidirecțional (`.vc2/.sc2/.fr2/.mn2/.dc2/.lb2`) | **De folosit.** Complet, fidel, include corpul metodelor, parametri, comentarii |
| vcx2prg | `D:\ROA\UTIL\vcx2prg\x2prg.prg` | Doar `.vcx``.prg` *compilabil* | Alternativă; mai vechi, doar clase, necesită IDE VFP deschis pentru a rula forma |
| prgtovcx | `D:\ROA\UTIL\prgtovcx\prgtovcx.PRG` | Invers: `.prg``.vcx` | **Nu** pentru căutare (e direcția opusă) |
FoxBin2Prg e prima alegere: rulează din linia de comandă fără IDE deschis (EXE compilat), acoperă
toate tipurile de container, și produce text mult mai fidel decât vcx2prg.
> Dacă `FoxBin2Prg.EXE` lipsește, se compilează o singură dată: deschide
> `D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2` în VFP 9 și *Build > Build Executable*. Lângă EXE trebuie
> să existe `filename_caps.exe` și fișierele `props*.txt` (sunt deja în folder).
## Mod recomandat: scriptul `vcx2txt.ps1`
`D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1` automatizează tot: copiază binarul + memo-ul într-un
**cache** care oglindește structura proiectului (ca să nu murdărească arborele SVN), rulează
FoxBin2Prg, păstrează doar fișierul text. E **incremental** (sare peste ce e deja la zi).
**Implicit e „project mode"**: citește `roaacnpro.PJX` și convertește **doar** fișierele
`.vcx`/`.scx` pe care le folosește efectiv proiectul (~78), **nu** tot `COMUN\` (care are zeci de
librării nefolosite în ROAACNPRO — pierdere de timp). Lista de fișiere vine direct din proiect, deci
e exactă.
```powershell
# DOAR fișierele proiectului (recomandat, rapid) -> cache text
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1
# include și rapoartele (.frx) și meniurile (.mnx)
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Types vcx,scx,frx,mnx
# conversie punctuală a unui fișier sau folder (chiar dacă NU e în proiect)
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source D:\ROA\ROAACNPRO\COMUN\clase\caut.vcx
# rebuild curat (șterge cache-ul întâi) / forțează reconversia
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Clean
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Force
```
Parametri utili: `-Project <alt.pjx>` (alt proiect, ex. `importroris.pjx`), `-Types`,
`-Source`, `-Clean`, `-Force`.
Rezultatul ajunge în `D:\ROA\UTIL\foxbin2prg\_textcache\` cu aceeași structură de directoare ca
proiectul (ex.: `_textcache\Clase\oacnpro.vc2`, `_textcache\comun\clase\_frm_base.vc2`). Apoi:
```bash
# cu unealta Grep (preferat) sau grep:
grep -rn "PROCEDURE do_calcul_tarife" "D:\ROA\UTIL\foxbin2prg\_textcache"
grep -rln "factura_salvare" "D:\ROA\UTIL\foxbin2prg\_textcache" # ce clase ating subiectul
```
Flux tipic pentru o problemă: rulează scriptul fără parametri o dată (populează cache-ul), apoi
caută cu `Grep` în `_textcache`. La sesiuni următoare rescrie doar ce s-a schimbat (incremental).
Dacă ai nevoie de o librărie din `COMUN\` care nu e în proiect, convertește-o punctual cu `-Source`.
## Alternativă manuală (fără script)
FoxBin2Prg scrie textul **lângă sursă**. Ca să nu murdărești `Clase/`, copiază perechea
binar+memo într-un folder temporar și convertește acolo:
```powershell
# .vcx -> .vc2 (cType gol = extensia decide direcția BIN2PRG)
Copy-Item D:\ROA\ROAACNPRO\Clase\oacnpro.vcx, D:\ROA\ROAACNPRO\Clase\oacnpro.vct D:\tmp\
& 'D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE' 'D:\tmp\oacnpro.vcx' '' '' '' '1' '0' '1'
# => D:\tmp\oacnpro.vc2
```
Pozițiile parametrilor folosite: `fișier, cType, cTextName, lGenText, cDontShowErrors=1,
cDebug=0, cDontShowProgress=1`. **Lasă `cType` gol** — extensia (`.vcx`) determină direcția.
(Nu da explicit `"BIN2PRG"` pentru un singur fișier: în acel mod EXE-ul așteaptă un *director*.)
Detalii complete de parametri: `D:\ROA\UTIL\foxbin2prg\docs\FoxBin2Prg_Run.md`.
## Soluție rapidă „murdară" (un singur fișier, fără conversie)
Pentru o verificare rapidă „există metoda X undeva în librărie?", `grep` merge direct pe `.vct`
(o vede ca binar, dar găsește potrivirile):
```bash
grep -c "PROCEDURE" "D:\ROA\ROAACNPRO\Clase\oacnpro.VCT"
grep -a -o "PROCEDURE [a-zA-Z0-9_]*" "D:\ROA\ROAACNPRO\Clase\oacnpro.VCT"
```
Bun pentru „da/nu" și nume de metode; pentru citit corpul/contextul, folosește conversia în text.
## Corespondență extensii binar → text
| Container | Binar (+memo) | Text |
|---|---|---|
| Librărie clase | `.vcx` + `.vct` | `.vc2` |
| Formă | `.scx` + `.sct` | `.sc2` |
| Raport | `.frx` + `.frt` | `.fr2` |
| Etichetă | `.lbx` + `.lbt` | `.lb2` |
| Meniu | `.mnx` + `.mnt` | `.mn2` |
| Bază de date | `.dbc` + `.dct` | `.dc2` |
## Note
- Codul aplicației stă mai ales în `Clase\*.vcx`; cea mai mare parte din `.vcx`-uri sunt în
`COMUN\` (framework partajat — vezi `CLAUDE.md`).
- `_textcache\` e regenerabil și e în afara arborelui SVN — poate fi șters oricând.
- Conversia **nu** necesită IDE-ul VFP deschis (folosește EXE-ul compilat).

View File

@@ -0,0 +1,359 @@
# Fluxuri de calcul și facturare pe tipuri de prestații
Acest document descrie **lanțul complet de facturare end-to-end** pentru fiecare tip de
prestație: **Import → Calcul → Salvare → Listare**. Scopul este să nu mai fie nevoie de fiecare
dată să se caute prin cod *cum* se ajunge de la datele sursă la valoarea facturată.
Documente complementare (a NU se duplica):
- `docs/facturare.md` — fluxul general de salvare a facturii (form `frm_factura`
`factura_salvare_db``PACK_FACTURARE.pck`), structura `crsFactura`, formulele de TVA.
- `docs/cautare_vcx_vct.md` — cum se caută cod în binarele `.vcx`/`.scx`.
Constante tipuri prestații: `Include/roaacnpro.h` (string `TIP_*`, numeric `NTIP_*`).
Codul de calcul al claselor de formular stă în binarul `Clase/oacnpro.vcx`; referințele de mai jos
folosesc cache-ul TEXT `_textcache/clase/oacnpro.vc2` (vezi `docs/cautare_vcx_vct.md`).
> Notație: `fișier:linie`. Pentru clase, `oacnpro.vc2:NNNN` = `_textcache/clase/oacnpro.vc2`.
---
## 0. Convenții de rotunjire
Rotunjirile folosesc constante globale de precizie, promovate din `RoaApp` (framework COMUN):
| Constantă | Rol | Valoare uzuală |
|-----------|-----|----------------|
| `gnPC` | precizie valori în monedă națională (lei) | 2 |
| `gnPVal` | precizie valori în valută | 2 |
| `gnZ` | precizie penalități (testat în cod: 2 — `proceduri_acnpro.prg:1542`) | 2 |
| `gnPCant` | precizie cantitate | (config) |
| `gnPPret` / `gnPPretV` | precizie preț unitar (lei / valută) | (config) |
| `gnPcurs` | precizie curs valutar | (config) |
Aceste constante sunt setate la inițializarea aplicației din configurația firmei (COMUN); nu sunt
hard-codate în acest repo. Acolo unde formula folosește un număr fix de zecimale (ex. `Round(..., 2)`,
`Round(..., 3)`, `Round(..., 4)`) acela este intenționat și independent de configurație.
---
## 1. IMPORT DATE (sursă RORIS)
### 1.1. Sinonime Oracle către schema `roris`
Datele sursă sunt tabele din sistemul extern **RORIS**, expuse aplicației prin **sinonime** create
în `database.txt`. Toate `ips_*` sunt sinonime spre `roris.ips_*`:
- `ips_voyages`, `ips_voyage_members`, `ips_voyage_locks` — voiaje, membrii convoiului, ecluzări
(`database.txt:2-3,11`).
- `ips_berthings` / `ips_vberthings` — staționări la dană (cheiaj) (`database.txt:15,17`).
- `ips_cargoes`, `ips_goods`, `ips_goods_groups` — mărfuri și grupe de marfă (`database.txt:7-9`).
- `ips_routes` / `ips_vroutes`, `ips_route_points` — rute și puncte de rută (distanțe)
(`database.txt:5,16,24`).
- `ips_vessels`, `ips_vessel_types`, `ips_vas_echivalent`, `ips_grup_tip_nave` — nave, tipuri,
echivalențe UM, grupe de tip navă (`database.txt:4,10,13,14`).
- `ips_vas_um` — unități de măsură ale tarifelor (`database.txt:12`).
- Vederile `ips_v*` (ex. `ips_vberthings`, `ips_vvoyages`, `ips_vroute_points`) sunt versiuni
pre-join ale acelorași date.
Tabelele proprii ale aplicației (NU sinonime): `ips_voyages_vanzari`, `ips_voyage_members_vanzari`,
`ips_regdoc`, `vanzari`, `factura`, `penalitati`, `contracte`, `ips_vtarife_tranzit`,
tarifele de cheiaj/contract.
### 1.2. Importul propriu-zis
Importul rulează ca **executabil separat** `importroris.exe` (proiect `importroris.pjx`), NU din
aplicația principală:
- Punct de intrare: `Programe/importroris_main.prg` — rulează silentios (`importroris s nnn`,
unde `nnn` = nr. zile) sau cu formular (`Do Form importroris`) (`importroris_main.prg:32-37`).
- Importul efectiv este delegat unui **pachet Oracle**:
`pack_acn_import.import_roris_job(?ptLastGenerationTime)` (`importroris_proceduri.prg:33`).
Toată extragerea/normalizarea din `roris.*` în tabelele locale `ips_*` se face în pachetul PL/SQL,
nu în VFP.
### 1.3. Câmpuri sursă relevante pentru calcul
La calcul, datele importate sunt citite din vederi de calcul:
- **Tranzit**: vederea `ips_vvoyage_members_calcul` (citită în `calcul_tranzit`,
`proceduri_acnpro.prg:835`). Câmpuri-cheie: `distanta`, `distanta_cdmn` (km pe canal),
`tcap` (capacitate/tone), `trn` (NRT), `lbd`, `hp`, `cuplat`, `periculos`, `procdiv`,
`gds_id`/`gdsg_id` (marfă/grupă marfă), `vtp_id`/`vgrp_id` (tip/grupă navă), `rte_id` (rută),
`cargo` (cantitate marfă). Schema cursorului `crsVoyages` în `proceduri_acnpro.prg:838-844`.
- **Cheiaj**: vederea `ips_vberthings` (citită în `calcul_cheiaj`, `proceduri_acnpro.prg:1023`).
Câmpuri: `datai`/`datap` (intrare/plecare → durată), `cap`, `trn`, `lbd`, `hp`, `lung`,
`tipn_id`, `dana_id`/`rpt_id` (dana). Schema `crsBerthings` în `proceduri_acnpro.prg:1028`.
- **Ecluzări** (tranzit): `ips_vvoyage_locks` (defalcate pe membru și cameră de ecluzare), citite
la distribuția pe ecluze în `completeaza_regdoc_tranzit` (`proceduri_acnpro.prg:2325`).
---
## 2. CALCUL TARIFE ȘI VALORI
Calculul se face în clasele de formular din `Clase/oacnpro.vcx`. Lanțul pentru tranzit/cheiaj este:
`frm_tranzit.do_executa``calcul_tranzit`/`calcul_cheiaj` (umplu cursoarele din RORIS) →
formularul de calcul (`frm_calcul_tranzit` / `frm_calcul_cheiaj`) → metoda de calcul tarife.
### 2.1. TRANZIT
- **Pregătire date**: `calcul_tranzit(tcVyeIds)``proceduri_acnpro.prg:740`. Creează `crsVoyage`
(convoaie) și `crsVoyages` (membrii, cu indicatorii din `ips_vvoyage_members_calcul`).
- **Calcul valoare**: clasa `frm_calcul_tranzit`, metoda **`do_executa`** —
`oacnpro.vc2:3651-3918`.
**De unde vin tariful și cantitatea:**
- Tarifele: `IPS_VTARIFE_TRANZIT` (join cu `IPS_VVAS_UM`), selectate de DOUĂ ori:
- tarife pe **contract** (`ctr_id = lnClientCtrId`) — `oacnpro.vc2:3688-3694` (cursor `tTarife`);
- tarife **generale/fără contract** (`ctr_id = get_ctr_id_fara_contract()`) —
`oacnpro.vc2:3698-3703` (cursor `tTarife2`).
- Selecția tarifului se face pe tip UM (`TC`/`TRN`/`LBD`/`HP`), încadrarea pe capacitate
(`TCAP1/TCAP2` la capacitatea totală a convoiului, `TCCAP1/TCCAP2` la capacitatea cumulată a
clientului), rută (`RTE_ID`) și grupă/tip marfă (`GDSG_ID`/`GDS_ID`) — `oacnpro.vc2:3750-3812`.
Ordinea de căutare: contract+marfă → general+marfă → contract+grupă → general+grupă → "orice
marfă" (`GDSG_ID=0`).
- Cantitatea (`cant`) depinde de UM: `TC``tcap`, `TRN``trn`, `LBD``lbd`, `HP``hp`
(`oacnpro.vc2:3768-3795`).
**Coeficienți** (`oacnpro.vc2:3717-3727, 3861-3865`):
- `corect` (coeficient corector): pornește de la 100, +`gnACNPFmarfa` (fără marfă), +`gnIpsPCuplat`
(necuplat), +`gnIpsPPericulos` (marfă periculoasă); apoi normalizat:
`corect = Round(lnCoeficient/100, 3)` (`oacnpro.vc2:3861`).
- `procdiv` — coeficient suplimentar adus din sursă (`Nvl(procdiv,0)`).
- `procdist` (coeficient distanță): **km din 64.4** (lungimea canalului), plafonat la 1:
```
Replace procdist With MIN(Round(Abs(distanta) / 64.4, 2), 1.00) && oacnpro.vc2:3864
```
**Formula valorii pe navă** (`oacnpro.vc2:3867`):
```
valval = Round(tarif * cant * procdist * (corect + procdiv), 2)
```
**Valoare minimă / valoare finală manuală** (`oacnpro.vc2:3877-3910`):
- Suma pe convoi: `lnValoareConvoi = SUM(valval) FOR ales=1`.
- Dacă `lnValoareConvoi <= valoare_minima_convoi` (`gnIpsValoareMinConvoi`) și > 0 și nu s-a scris
manual, valoarea finală devine valoarea minimă (`oacnpro.vc2:3883-3885`).
- Dacă utilizatorul a scris o **valoare finală** diferită, valorile se distribuie proporțional:
```
Replace All VALVAL With Round(lnValoareFinala * VALVAL / lnValoareConvoi, gnPC) For ales = 1 && oacnpro.vc2:3891
```
Diferența de rotunjire dintre suma recalculată și valoarea finală se pune pe primul rând
(`oacnpro.vc2:3903-3907`). La stornare (val. finală < 0) se recalculează cantitatea
(`oacnpro.vc2:3895`); tariful NU se recalculează (apare tariful de încadrare pe recapitulație).
**Rotunjiri tranzit:** `procdist`→2 zecimale, `corect`→3 zecimale, `valval`→2 zecimale fix;
distribuția valorii finale→`gnPC`.
### 2.2. CHEIAJ
- **Pregătire date**: `calcul_cheiaj(tcVyeIds)` — `proceduri_acnpro.prg:963`. Creează `crsVoyage`,
`crsBerthings` (staționări din `ips_vberthings`) și `crsBerthingDetails` (prestații de facturat).
- **Calcul valoare**: clasa `frm_calcul_cheiaj`, metoda **`do_calcul_tarife`** —
`oacnpro.vc2:1191-1375`.
**Durata** (oră → UM tarif): `lnDurata1 = Round((datap - datai)/3600, 3)` ore
(`oacnpro.vc2:1228`), apoi împărțită la `corect` pentru transformare în UM tarifului (ore sau zile)
și, dacă tariful are flag `plus`, rotunjită în sus cu `Ceiling()` (`oacnpro.vc2:1289-1292`).
**Tariful**: `crsTarifeDiverseContract` construit de `make_tarife_cheiaj_contract` cu tarifele de
contract și cele generale (`oacnpro.vc2:1215`). Încadrarea pe interval de durată:
`lim1*corect < durata AND lim2*corect >= durata`, după `ctr_id`, `id_articol`, `intern`
(`oacnpro.vc2:1247-1248`).
**Cantitatea** după UM tarif (`oacnpro.vc2:1298-1313`): `ZI`→1 (ex. cheiaj iernat),
`TC`→`cap`, `TRN`→`trn`, `ML`→`lung`, `CP`/`HP`→`hp`, `LBP`/`LBD`→`lbd`. Dacă UM conține `ZI`,
valoarea se înmulțește și cu numărul de zile (`llZile`).
**Formula valorii** (`oacnpro.vc2:1320-1345`):
- Caz simplu (fără bază): `valval = tarif * cant * IIF(llZile, durata, 1)` (`oacnpro.vc2:1342`).
- Caz cu **tarif pe tranșe** (`arebaza=1`): se cumulează tarifele tranșelor inferioare
(`baza=1`) plus tranșa curentă pentru durata rămasă (`oacnpro.vc2:1321-1343`).
- `valval = Round(valval, gnPVal)` (`oacnpro.vc2:1345`).
**Valoare finală manuală** (`oacnpro.vc2:1356-1367`): distribuție proporțională
`Round(lnValoareFinala * valval / lnValoareConvoi, gnPVal)`, recalcul cantitate
`Round(valval/tarif, 2)`, diferența pe primul rând.
### 2.3. CHIRII (și contracte similare)
- **Calcul valoare**: clasa `frm_calcul_contract` — `oacnpro.vc2:1615`. Lucrează cu
`crsArticoleContract` (linii introduse pe baza articolelor de contract), NU pe date RORIS.
- Metode: `calculeazapreturi` (`oacnpro.vc2:2240`) → `calculeazapreturirand`
(`oacnpro.vc2:2248`) → `calculeazatotaluri` (`oacnpro.vc2:2267`).
**Formula** (`calculeazapreturirand`, `oacnpro.vc2:2256-2262`):
- la modificarea cantității/prețului: `valval = Round(pret * cantitate, gnPC)`;
- la modificarea valorii (recalc preț unitar): `pret = Round(valval/cantitate, 4)`.
Tariful (`pret`) provine din articolul de contract (introdus de utilizator / tarif contract);
nu există coeficient de distanță sau corecție.
### 2.4. PENALITĂȚI
- **Calcul valoare**: clasa `frm_penalitati` — `oacnpro.vc2:8366`. Metoda `do_executa`
(`oacnpro.vc2:9671`) apelează `calcul_penalitati2` (`proceduri_acnpro.prg:1286`); varianta
cu vânzări reale este `calcul_penalitati` (`proceduri_acnpro.prg:1166`).
- Recalcul pe o linie editată: `calcul_penalitati_linie` (`proceduri_acnpro.prg:1455`).
**De unde vin datele**: facturi/încasări din `vanzari`, `vact`, `ireg_parteneri`; cotele de
penalitate din `contracte` (`coef_penalitati`→`ppenzi`, `coef_penalitati2`→`ppenzi2`,
`zile_penalitati`→`penzile`, `zile_gratie_penalitati`→`zilegratie`)
(`proceduri_acnpro.prg:1183,1225`). Cursorul de lucru: `crsCalculPenalitati`.
**Zile de întârziere** (`proceduri_acnpro.prg:1257-1265`):
- `databaza` = `Max(datascad, sfârșit lună precedentă)` sau `datascad` (după modul de calcul);
- `dataref` = `Min(dataref, pdDataReferinta)`;
- `nr_zile = IIF(dataref - databaza <= zilegratie, 0, dataref - databaza)` (zile de grație).
**Formula penalitate, o singură cotă** (`proceduri_acnpro.prg:1266`):
```
penalitati = Round(Round(ppenzi/100*suma, gnZ) * nr_zile, gnZ)
```
**Formula penalitate, două cote** (`CalculeazaPenalitati`, `proceduri_acnpro.prg:1510-1539`):
- se împart zilele restante între cota 1 (până la `penzile2-penzile`) și cota 2 (peste);
vezi `lnZileProcent1`/`lnZileProcent2` (`proceduri_acnpro.prg:1531-1534`).
- ```
penalitati = Round(Round(ppenzi /100*suma, gnZ)*lnZileProcent1, gnZ)
+ Round(Round(ppenzi2/100*suma, gnZ)*lnZileProcent2, gnZ) && proceduri_acnpro.prg:1536
```
- Aplicată în `calcul_penalitati` doar pentru contracte cu `ppenzi2 <> 0`
(`proceduri_acnpro.prg:1271-1277`).
**Rotunjiri**: toate la `gnZ` (dublă rotunjire: întâi penalitatea/zi, apoi totalul). Funcția de
test cu valori așteptate: `TestCalculeazaPenalitati` (`proceduri_acnpro.prg:1541`).
### 2.5. APA / PILOTAJ / ALTE / DIVERSE
Aceste tipuri **nu au un motor de calcul propriu** bazat pe RORIS. Sunt facturate prin lanțul
generic de contract/articol:
- Calculul valorii este `pret * cantitate` (vezi 2.3 CHIRII, `frm_calcul_contract` /
`calculeazapreturirand`, `oacnpro.vc2:2256-2262`), respectiv introducere directă pe linia de
factură în `frm_factura` (`crsFactura`, vezi `docs/facturare.md`).
- Tariful provine din articol/contract (`ips_vprestatii_locatii`, `contracte`), nu există
coeficienți de distanță/corecție.
- Constantele de tip: `NTIP_APA 2`, `NTIP_PILOTAJ 4`, `NTIP_ALTE 5`, `NTIP_DIVERSE 9`
(`Include/roaacnpro.h`).
- Salvarea acestor linii se face în `ips_regdoc` prin `salvare_contract`
(`proceduri_acnpro.prg:1918`).
---
## 3. SALVARE FACTURĂ
Fluxul general (cap factură, articole, vânzări, contabilitate) este în `docs/facturare.md`;
sursa de adevăr pentru valori/TVA este **`PACK_FACTURARE.pck`**. Aici se documentează doar
specificul fiecărui tip.
### 3.1. Lanțul comun
- `factura_acn(tcTip, loDate)` — `proceduri_acnpro.prg:3064` — orchestrarea facturii.
- `factura_salvare_db(tcTip)` — `proceduri_acnpro.prg:3290` — persistarea:
- `pack_facturare.initializeaza_date_factura(...)` (cap factură), `adauga_articol_factura_deviz`
(articole), `scrie_in_vanzari` (`proceduri_acnpro.prg:3343,3382,3412`);
- reg. doc.: `pack_acn.salveaza_regdoc(...)` pentru fiecare rând din `cRegDoc`
(`proceduri_acnpro.prg:3430`);
- pentru TRANZIT/CHEIAJ: actualizează `ips_voyages_vanzari.vz_id` cu id-ul vânzării
(`proceduri_acnpro.prg:3448-3451`);
- pentru PENALITĂȚI: inserează în tabela `penalitati` (`proceduri_acnpro.prg:3475-3488`).
### 3.2. TRANZIT — specific
- `salvare_tranzit` — `proceduri_acnpro.prg:1779`:
- inserează capul de convoi facturat în **`IPS_VOYAGES_VANZARI`** (`...:1788-1791`);
- inserează fiecare navă în **`IPS_VOYAGE_MEMBERS_VANZARI`** cu toate valorile calculate
(`procdist`, `corect`, `tarif`, `cant`, `valval`, `distanta`, `distanta_cdmn`, etc.)
(`...:1794-1849`). Tranzacție manuală cu COMMIT/ROLLBACK.
- `completeaza_regdoc_tranzit(tcVVIds)` — `proceduri_acnpro.prg:2259` — **distribuția pe canale și
ecluze**:
- procentul CDMN al fiecărei nave: `Round(DISTANTA_CDMN / DISTANTA, 4)` (`...:2332`);
- valori CDMN = `valval * procentCDMN`, PAMN = restul (`...:2355-2364`);
- valori pe **senale navigabile** = valoarea CDMN/PAMN × procentul de senal
(`100 - procente_ecluze`)/100 (`...:2369-2385`);
- procentele pe ecluze (`AGIGEA`/`CERNAVODA`/`OVIDIU`/`NAVODARI`) din `ips_vvoyage_locks` și
constantele `gnIPSTranzitProcAG/CV/OV/NV` (`...:2289-2324`).
### 3.3. CHEIAJ — specific
Salvarea se face tot prin `IPS_VOYAGES_VANZARI` / `IPS_VOYAGE_MEMBERS_VANZARI` (același mecanism ca
tranzit, cu `poVoyage.tip = NTIP_CHEIAJ`) și prin lanțul comun din 3.1 (`vz_id` actualizat la
`factura_salvare_db`, `proceduri_acnpro.prg:3448`). `make_factura_cheiaj`
(`proceduri_acnpro.prg:3615`) construiește linia de articol în `crsFactura`.
### 3.4. CHIRII / APA / PILOTAJ / ALTE / DIVERSE — specific
- `salvare_contract` — `proceduri_acnpro.prg:1918` — inserează în **`ips_regdoc`** (tip, articol,
locație, valută, client, contract, preț, cantitate, valval, TVA, perioadă) (`...:1924-1953`).
### 3.5. PENALITĂȚI — specific
- `salvare_penalitati` — `proceduri_acnpro.prg:2008` — marchează înregistrările alese/șterse;
scrierea reală în tabela `penalitati` se face în `factura_salvare_db`
(`proceduri_acnpro.prg:3475-3488`).
- `make_factura_penalitati` — `proceduri_acnpro.prg:3775` — construiește linia de factură.
---
## 4. LISTARE FACTURĂ + RECAPITULAȚIE
Rapoartele citesc, în general, **valorile deja calculate** din tabelele de vânzări; recapitulațiile
recalculează doar agregări/distribuiri pentru afișare, nu tarife.
### 4.1. Construirea liniilor de factură (`crsFactura`)
- `make_factura_tranzit` — `proceduri_acnpro.prg:3517`: citește valorile însumate din
**`ips_voyage_members_vanzari`** (`SUM(valval)` pe valută, `proceduri_acnpro.prg:3561-3567`),
numele convoiului din `ips_vvoyages` și completează `crsFactura` (un singur rând, cantitate 1,
preț = valval în monedă națională). NU recalculează tarife.
- `make_factura_cheiaj` — `proceduri_acnpro.prg:3615`: analog, pentru cheiaj.
- `make_factura_penalitati` — `proceduri_acnpro.prg:3775`.
### 4.2. Recapitulații (rapoarte `Rapoarte/*.frx`)
Procedurile de generare a cursoarelor de raport: `Programe/proceduri_acnpro_rapoarte.prg` și
proceduri din `proceduri_acnpro.prg`:
- **Recapitulație tranzit**: `listeaza_recapitulatie_tranzit` — `proceduri_acnpro.prg:5504`.
Citește **`ips_vvoyage_members_vanzari`** `WHERE vz_id = ?pnIdVanzare`
(`...:5515-5584`) — toate valorile (`tarif`, `cant`, `procdist`, `corect`, `valval`, `valctva`...)
sunt deja calculate și salvate; raportul le afișează. Capacitatea totală a convoiului se
recalculează cu fereastră `LAST_VALUE(...) OVER(PARTITION BY vms_id)` (`...:5599-5613`).
Modul de calcul afișat (textul formulei) se generează cu `mod_calcul_tranzit`
(`proceduri_acnpro.prg:5728`): `TARIF * CANT * %DIST * (%COR + %SUPL) = TOTAL`
(`...:5736,5746`).
- **Recapitulație cheiaj**: `listeaza_recapitulatie_cheiaj` — `proceduri_acnpro.prg:5368`.
- **Recapitulație penalități**: `listeaza_recapitulatie_penalitati` —
`proceduri_acnpro.prg:5777`. Din factură citește din vederea `vpenalitati`
`WHERE id_fact_pen = ?pnIdFact` (`...:5809-5836`); din formularul de calcul (evaluare) folosește
cursorul `crsRecapitulatie` deja calculat. Valorile penalităților NU se recalculează la listare.
- Rapoarte `.frx` asociate: `Rapoarte/factura*.frx`, `recapitulatie_tranzit`,
`recapitulatie_cheiaj`, `recapitulatie_penalitati`, `registru tranzit`.
**Regula generală**: la listare se citesc valori **deja calculate** (din
`ips_voyage_members_vanzari`, `vpenalitati`, `ips_regdoc`/`vanzari`). Singurele recalculări la
listare sunt: textul „mod de calcul" (`mod_calcul_tranzit`) și agregările/încadrările de capacitate
pe recapitulația de tranzit.
---
## 5. Capcane cunoscute
1. **Coeficientul de distanță rotunjit la 2 zecimale poate deveni 0.**
`procdist = MIN(Round(Abs(distanta)/64.4, 2), 1.00)` (`oacnpro.vc2:3864`). Pentru distanțe sub
~0.32 km (0.005 × 64.4) `Round(.../64.4, 2)` dă 0 → `valval = tarif*cant*0*(...) = 0`. Câmpul
`PROCDIST` este `N(6,3)` în schema cursorului (`proceduri_acnpro.prg:843`) și în
`ips_voyage_members_vanzari`, deci ar putea stoca 3 zecimale, dar **calculul rotunjește la 2**,
nu la 3 — distanțele foarte mici se facturează cu valoare 0.
2. **Împărțire la 0 la valoarea finală.**
La distribuirea valorii finale introduse manual:
`Round(lnValoareFinala * VALVAL / lnValoareConvoi, gnPC)` (`oacnpro.vc2:3891`, tranzit; analog
`oacnpro.vc2:1360`, cheiaj). Dacă valoarea convoiului calculat (`lnValoareConvoi`) este 0 (de
ex. toate `valval=0` din cauza capcanei 1, sau tarife 0), împărțirea dă eroare/`NaN`. Codul
protejează parțial (condiția `lnValoareConvoi > 0` la valoarea minimă, `oacnpro.vc2:3883`), dar
ramura cu valoare finală scrisă manual (`oacnpro.vc2:3887`) nu verifică `lnValoareConvoi <> 0`
înainte de împărțire.
3. **Tariful NU se recalculează la valoarea finală (tranzit).** Intenționat: pe recapitulație apare
tariful de încadrare, nu cel rezultat din valoarea finală (`oacnpro.vc2:3896-3899`). Diferența
de rotunjire ajunge pe primul rând (`oacnpro.vc2:3906`), deci `valval` al primului rând poate
diferi de `tarif*cant*procdist*(corect+procdiv)`.
4. **Penalități — dublă rotunjire.** Formula rotunjește întâi penalitatea/zi și apoi totalul
(`Round(Round(ppenzi/100*suma, gnZ)*nr_zile, gnZ)`, `proceduri_acnpro.prg:1266`). Pentru cele
două cote, fiecare termen este rotunjit separat și apoi însumat (`proceduri_acnpro.prg:1536`),
deci totalul poate să nu fie egal cu `Round(total_brut, gnZ)`.
5. **`calcul_penalitati2` folosește `ireg_parteneri` în loc de `vanzari`** (temporar, până la
importul vânzărilor) — comentariu în cod (`proceduri_acnpro.prg:1284-1286`,
`oacnpro.vc2:9678`). Rezultatele pot diferi de `calcul_penalitati` până la stabilizare.
6. **Distribuția CDMN depinde de `DISTANTA <> 0`.** `Round(DISTANTA_CDMN/DISTANTA, 4)`
(`proceduri_acnpro.prg:2332`) — dacă `DISTANTA` este 0, distribuția pe canale/ecluze eșuează.

BIN
importroris.PJT Normal file

Binary file not shown.

BIN
roaacnpro.PJT Normal file

Binary file not shown.

Binary file not shown.

BIN
verificare_roris_ecluze.PJT Normal file

Binary file not shown.