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>
This commit is contained in:
@@ -120,6 +120,12 @@ throughout the codebase:
|
|||||||
the `crsFactura` structure, the VAT formulas, and which files to touch for a given task. Key
|
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
|
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.
|
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
|
- **`Programe/proceduri_acnpro_rapoarte.prg`** — report-generation procedures feeding the
|
||||||
`Rapoarte/*.frx` layouts (factura, recapitulatie_cheiaj/tranzit/penalitati, registru tranzit).
|
`Rapoarte/*.frx` layouts (factura, recapitulatie_cheiaj/tranzit/penalitati, registru tranzit).
|
||||||
- **`Programe/importroris*.prg`** + `importroris.pjx` — a *separate* small executable
|
- **`Programe/importroris*.prg`** + `importroris.pjx` — a *separate* small executable
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -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 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
|
Select cModCalculTemp
|
||||||
Scan
|
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, 3)) + [ * ] + Allt(Str(corect + procdiv, 5, 3)) + [ = ] + Alltrim(Transform(valval, GET_MASK(16, 2))) + [ ] + Allt(valuta)
|
||||||
llIntern = intern
|
llIntern = intern
|
||||||
lnCurs = Curs
|
lnCurs = Curs
|
||||||
If m.llIntern
|
If m.llIntern
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
<!--
|
||||||
|
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
|
10/06/2026
|
||||||
ROAACNPRO - 2.0.4
|
ROAACNPRO - 2.0.4
|
||||||
|
|||||||
359
docs/fluxuri_calcul_facturare.md
Normal file
359
docs/fluxuri_calcul_facturare.md
Normal 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
roaacnpro.PJT
BIN
roaacnpro.PJT
Binary file not shown.
BIN
roaacnpro.PJX
BIN
roaacnpro.PJX
Binary file not shown.
Reference in New Issue
Block a user