Files
roagest/CLAUDE.md

23 KiB
Raw Permalink Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this is

ROAGEST is a Visual FoxPro 9 desktop application (Romanian-language) for gestiune de stocuri și mărfuri — goods/inventory management: purchases (achiziție, NIR — notă intrare recepție), sales, warehouse transfers, stock (stoc), consumption vouchers (bon consum), inventory counts (inventar), price changes (schimbare preț), and cash-register (casă de marcat, e500/mp500) integration. It backs onto an Oracle database (gcS schema, default CONTAFIN) reached through the shared goExecutor/goConn SQL pass-through objects. It is one member of the larger "ROA" suite built by ROA Romfast SRL (ROAACNPRO, ROAIMOB, ROACONT, ROACASA, ROADEF, etc.) and lives alongside its siblings under D:\ROA.

The code, comments, menus, and changelog are all in Romanian — match that language when editing user-facing strings, comments, and changelog entries.

Architecturally, ROAGEST is older-generation than ROAACNPRO/ROAIMOB: those apps instantiate oApp as a subclass of the shared RoaApp framework class (COMUN/programe/roa.prg) with an ordered initializeaza* method pipeline. ROAGEST does not use RoaApp at all — COMUN/programe/roa.prg exists in this repo (vendored, shared with the other apps) but is unreferenced. Instead, Programe/roagest.prg is a long, monolithic startup script that manually chains SET PATH/SET CLASSLIB ... ADDITIVE/SET PROCEDURE ... ADDITIVE statements and instantiates goApp = CREATEOBJECT("wzApplication") — the classic VFP "Application Wizard" base class (defined in COMUN/clase/appwiz.vcx). Don't assume the RoaApp/initializeaza* conventions documented for ROAACNPRO/ROAIMOB apply here.

Build, run, version control

  • Build/run requires the Visual FoxPro 9 IDE on Windows. There is no command-line build. Open roagest.pjx in the VFP IDE and use Project > Build to produce roagest.exe. The startup program is Programe/roagest.prg.
  • .prg files are source; .fxp/.FXP are compiled, .BAK are backups. Edit the .prg. The .scx/.sct (forms), .vcx/.vct (class libraries), .frx/.frt (reports), and .mnx/.mnt/.mpr (menus) are VFP binary/generated artifacts — edit them in the VFP IDE, not by hand. .mpr/.mpx are GENMENU-generated from .mnx; never hand-edit them.
  • SVN remains the "live" source of truth, especially for COMUN/ — use svn, not git, for the authoritative history. A git repo now runs in parallel (see "Version control: git alongside SVN" below).
  • config.fpw sets the runtime environment (CODEPAGE=1252, EXCLUSIVE=OFF, SAFETY=OFF, MULTILOCKS=ON, TALK=OFF). Don't enable SAFETY — the code relies on silent overwrite. Programe/roagest.prg re-asserts most of these plus SET DATE TO DMY, SET DECIMALS TO 4, SET EXACT ON.
  • roagest.exe refuses to start unless its own filename matches gcNumeProgram = 'ROAGEST' (IF !LIKE(gcNumeProgram + '*', ...) near the top of roagest.prg) — a guard against running a renamed/copied executable.
  • The compiler error log is roagest.ERR; the runtime log is log.txt. roagest.Stats and versiune_db.txt (format YYYY_MM_DD_NN, e.g. 2026_01_21_02) track build/DB-schema stamps checked against the update server on launch (COMUN/programe/oupdate.prg, wwcodeupdate.prg).
  • Programe/cont2000.prg is a near-duplicate of roagest.prg (same startup pattern, older CONT2000 naming) still present in the tree — treat it as legacy/reference, not the active entry point, unless you confirm otherwise from roagest.pjx's main-file setting.

Version control: git alongside SVN

Git rulează în paralel cu SVN-ul legacy, nu îl înlocuiește. SVN rămâne sursa "vie" pentru COMUN/, sincronizat manual către git; nu rula comenzi svn din git și nu presupune că git-ul e la zi cu ultimele modificări SVN dacă nu a fost sincronizat explicit.

  • Repo-ul principal (rădăcina acestui folder) e propriul lui .git, cu remote git@gitea.romfast.ro:romfast/roagest.git. .gitignore exclude COMUN/ (gestionat separat, vezi mai jos), .svn/, artefactele VFP compilate (*.fxp, *.bak, *.mpr, *.exe, …) și fișierele Windows uzuale.
  • COMUN/ are propriul .git separat, cu remote git@gitea.romfast.ro:romfast/comun.gitacelași repo partajat de toate aplicațiile ROA (ROAACNPRO, ROAIMOB, etc.). O modificare împinsă acolo afectează toate proiectele. Nu face push --force peste comun.git fără aprobare explicită — ar șterge istoric comun tuturor proiectelor.
  • Căutarea în cod VFP binar (.vcx/.scx) pentru acest proiect folosește textul .??2 generat în arbore, lângă fiecare binar (vezi secțiunea de mai jos) — reîmprospătat cu git_sync.ps1 -ProjectRoot D:\ROA\ROAGEST, nu un cache separat.

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. Git tracks the FoxBin2Prg text versions of these binaries (.vc2/.sc2/.fr2/.mn2, plus .lb2/.pj2/.dc2/.db2), generated in-tree next to each binary — not the binaries themselves, which are git-ignored. Refresh with git_sync.ps1 (folder-mode, recursive, incremental):

powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\git_sync.ps1 -ProjectRoot D:\ROA\ROAGEST

Run it at the start of every session and before any git commit so the text matches the binaries. It converts in a temp staging area and copies back only the text, continues past per-file failures, and exits nonzero on any failure: do not commit while git_sync reports unexplained failures. Then search the .??2 files in-tree with Grep (e.g. PROCEDURE do_salvare), citing file:line.

For .vcx/.scx, code edits no longer require the VFP IDE — the flow is now:

  1. Refresh the in-tree text (git_sync.ps1 above), especially if a VFP IDE session ran since the last refresh (IDE changes make the text stale).
  2. Edit the .vc2/.sc2 text directly (position-sensitive format — don't reflow lines; properties are alphabetized).
  3. Review the diff on the text file like any other source change.
  4. Write back with txt2vcx.ps1 (D:\ROA\UTIL\foxbin2prg\txt2vcx.ps1 -TextFile <path\to\file.vc2> -ProjectRoot 'D:\ROA\ROAGEST') — it regenerates and recompiles the binary in a staging folder, fidelity-checks it against the edited text, then copies it into the project only if that check passes.

Grep can't tell which class/method a hit inside a .vc2 belongs to (the class header may be thousands of lines above it, and ~2/3 of the file is properties/metadata). vfp_symbols.ps1 indexes the line range of every class/method/procedure and labels hits with their owner — use it before any txt2vcx.ps1 edit to get the exact line range of the method you are changing. Its built-in defaults target ROAACNPRO, so always pass ROAGEST's paths:

$s = 'D:\ROA\UTIL\foxbin2prg\vfp_symbols.ps1'
$c = @('-CacheRoot', 'D:\ROA\ROAGEST', '-ProjectRoot', 'D:\ROA\ROAGEST', '-IndexFile', 'D:\ROA\_vfp_textcache\roagest\_symbols.tsv')

powershell -ExecutionPolicy Bypass -File $s @c -Grep '<expresie>' -CodeOnly   # hits labeled class.method, code only
powershell -ExecutionPolicy Bypass -File $s @c -Where '<fisier>.vc2:<linie>'  # who owns this line
powershell -ExecutionPolicy Bypass -File $s @c -Find '<nume>'                 # where it is DEFINED
powershell -ExecutionPolicy Bypass -File $s @c -Class '<nume_clasa>'          # inheritance chain + methods

The index (_symbols.tsv) rebuilds itself when the text is newer, so refresh the in-tree text first (git_sync.ps1) — it can't see IDE edits that were never converted. Full search guide: COMUN\docs\cautare_vcx_vct.md.

.mnx/.frx stay read-only in this flow (menus still need GENMENU in the IDE; reports are too fragile to round-trip) — edit those in the VFP IDE as before. Targets under COMUN\ need -AllowComun plus explicit approval, since a change there affects every ROA app. See D:\ROA\UTIL\foxbin2prg\CLAUDE.md for full details and COMUN\docs\flux-editare-vfp-text.md for the shared per-round workflow (baseline backups, review patches, fidelity check) plus the per-project parameters (including ROAGEST's).

The COMUN shared framework

COMUN/ is shared, framework-level code used by every ROA app — it is not specific to ROAGEST. Treat it as a vendored library:

  • A change in COMUN/ affects all ROA applications. Prefer making app-specific changes in this repo's top-level Programe/, Clase/, Ferestre/, Meniuri/, Rapoarte/ directories. Only touch COMUN/ when the fix genuinely belongs to the shared framework.
  • Unusually for this app, most of the actual "gestiune" business logic lives in COMUN/programe/, not in this repo's own Programe/. ROAGEST's own Programe/ folder has only ~24 files (roagest.prg, gestiuni.prg, cont2000.prg, oimportdinxml.prg, ofactureaza.prg, exportare.prg, fisa_ob_inventar.prg, update_nomenclator.prg, suma_in_vorbe.prg, actualizari.prg, cumplun-furn.prg, inchidere_k.prg, ovariabile_globale.prg, shutdown.prg), while the core stock/article/movement procedures — oproceduri_stocuri.prg, oproceduri_articole.prg, oproceduri_rulaje.prg, oproceduri_casademarcat.prg (+ _e500/_mp500 cash-register variants), oproceduri_facturare.prg, oproceduri_obinv.prg (fixed-asset-in-use items), anaf_efactura.prg (ANAF e-Factura), osecurity.prg, oproceduri_configurare.prg, oproceduri_listari.prg, oproceduri_retete.prg, orapoarte.prg — all resolve from COMUN/programe/ via SET PATH. Likewise most class libraries used (onomenclatoare, stocuri.vcx, rulaje.vcx, ointroduceri*, oinventar, orapoarte_gestiuni, bon_fisc, onom_articole, onom_retete, ferestre_oracle, configurare.vcx, serii_numere.vcx, …) live in COMUN/clase/, not this repo's Clase/.
  • ROAGEST's own Clase/ folder is small: gestiuni.vcx, oavize.vcx, oimportxml.vcx, orapoarte_gestiuni.vcx, ovizrul.vcx, atentie.vcx. Its own Ferestre/ is also small: fundal.scx (shell form), accesindivid.scx, frm_conversii.scx, frm_schimbare_pret_tva.scx. The bulk of forms actually used are COMUN\ferestre\* (e.g. login is COMUN\ferestre\frm_login.scx).
  • SET PATH (see Programe/roagest.prg ~line 109) makes COMUN\CLASE, COMUN\FERESTRE, COMUN\PROGRAME, COMUN\GRAFICE, COMUN\RAPOARTE, COMUN\MENIURI, and the COMUN\UTILE\* helper libraries (GridExtras, ctl32, hpdf/ReportOutput, web, Excel) resolvable by bare filename, plus a sibling ..\COMUNROA\ directory (built from gcAppPath's grandparent). So SET PROCEDURE TO email.prg resolves to COMUN\PROGRAME\email.prg.

Application architecture

Startup flow (Programe/roagest.prg, procedural — no oApp/RoaApp object wraps it):

  1. Verifies the running exe is actually named ROAGEST*; sets SET CENTURY/DELETED/DATE/EXACT/... environment options.
  2. Computes gcAppPath (own folder) and gcDirMare/dirgen (suite root, one level up — e.g. D:\ROA\), builds the long SET PATH TO string across its own folders + COMUN\* + ..\COMUNROA\, then issues dozens of ordered SET CLASSLIB ... ADDITIVE and SET PROCEDURE ... ADDITIVE statements (order matters: later ADDITIVE registrations can shadow earlier same-named procedures/classes).
  3. Parses the launch parameter string (tparam, semicolon-delimited: host;user;password;idutil;idprogram;...;an;luna;schema;idfirma) when launched by the central ROA launcher; otherwise falls back to hardcoded dev defaults (JCSSERVER/CONTAFIN_ORACLE).
  4. Sets up cross-cutting globals: goLog/poLog (Log_Mesaje.prg), goLocale (Romanian by default, glTraducere = .F. — translation path largely dormant), goExecutor/goConn (Oracle SQL pass-through), goExport, goMyXMLHTTP (remote error reporting), and an optional goKeepAlive timer (avoids ODBC idle timeouts).
  5. NUMEPROGRAM = 'ROA - Gestiuni', _program = 'gest'; reads the actual version string from the built .exe's file version resource.
  6. Registers ON SHUTDOWN ShutDown() / ON ERROR ErrorHandler(...), instantiates goApp = CREATEOBJECT("wzApplication"), sets goApp.cStartupMenu to Meniuri\roagest.mpr and goApp.cStartupForm to COMUN\ferestre\frm_login.scx, then goApp.SHOW — this is the VFP event loop entry (AppWizard's Show/Run machinery), analogous to READ EVENTS in the newer apps.
  7. ErrorHandler posts errors to a remote endpoint via goMyXMLHTTP.postError(...) (host read from settings.ini's [errors] host key) in addition to showing AMESSAGEBOX. Cleanup()/ShutDown() release class libs, procedures, and the menu stack on exit.

Globals convention

Same g/gc/gn/gl Hungarian-ish prefixing as the rest of the suite (g = global, gc/gn/gl = char/numeric/logical, m. = memory-variable scoping), declared PUBLIC/PRIVATE directly in roagest.prg rather than promoted by a framework object:

  • goApp (AppWizard app object), goConn/goExecutor (Oracle connection + SQL executor), goLog/poLog (logger), goLocale, goExport, goCalendar, goFirma.
  • gcS = Oracle schema (default CONTAFIN), gnIdFirma, gnAn/gnLuna (working year/month), gcAppPath (this app's folder), gcDirMare/dirgen (suite root, e.g. D:\ROA\), gcSecurityPath/gcSecurityFile (DIRGEN + 'Security\ROA_SECURITY.TXT'), gcGeneralIniFile/gcSettingsFile (DIRGEN + 'settings.ini').
  • Legacy holdovers from the pre-Oracle (CONT2000) codebase are still declared even though mostly unused now: nror[65000], RTVA[22,2], SER_PERM/SER_PERI/VERSIUNE (commented out), old disk-serial license-check functions (decodare1, HEXDEC, DECTOBIN, the commented-out PORNIRE/verif_ser_perm) — dead code kept for reference, not active.

Data layer

  • Backend is Oracle, reached via goConn/goExecutor (created from the DECABAZA classlib, same pattern as the sibling apps) — run queries with SQLEXEC()/the executor wrapper; results come back as VFP cursors.
  • Domain tables/views follow Romanian/domain naming: stoc, rulaje/rull (stock movements), act (documents/NIR), articole/nomenclator, gestiuni (warehouses/locations), casa de marcat bon fiscal tables. Look in COMUN/programe/oproceduri_stocuri.prg, oproceduri_articole.prg, and oproceduri_rulaje.prg for the canonical query/view names (e.g. viz_stocuri filters on an, luna, id_sucursala, id_gestiune).
  • Initializari/ holds XML templates for cash-register integrations (roagest_bon.xml(.tmpl), roagest_mp500.xml(.tmpl), euro500t.txt(.tmpl), euro500t_erori.xml(.tmpl)).
  • Locale/ is a full VFP database (locale.dbc + .dbf/.cdx) for the (largely dormant) translation feature, not just an .ini.

Domain quick reference

  • No app-specific .h include defines domain constants the way roaacnpro.h does for ROAACNPRO — Include/CONT2000.H is just a historical comment (a class-tree diagram from the old CONT2000 codebase), and Include/foxpro.h is the stock VFP header. Domain behavior (document types, movement signs, VAT handling) is expressed directly in procedure logic in COMUN/programe/oproceduri_*.prg, not centralized constants — expect to trace behavior through those procedures rather than a single defines file.
  • Rapoarte/*.frx (24 report layouts in this repo, more resolved from COMUN\RAPOARTE) name the real workflows: rap_nirtransfer_achi (NIR/transfer receiving), rap_centralizator_intrari/_intrari2, rap_centralizator_iesiri/_iesiri2 (in/out summaries), rap_fisa_magazie_fifo (FIFO stock card), rap_gest_val_subgrupe/_gestc (valued stock by subgroup), rap_vechime_stocuri (stock aging), rap_marfuri_lista_centr/_desf/_valoric (goods lists), rap_vanzari_comp_cant/_val/_web (sales comparisons), rap_instiintaripret (price-change notices), rap_inchidere_k, rap_stoc_obinv (inventory-use objects), rap_rul_consum_lucrari_articole/_centralizator_consum_lucrari (consumption vouchers).
  • Meniuri/ menu names map to the app's top-level operations: achi* (achiziții/purchases), vanz* (vânzări/sales), consum* (bon consum), transfer* (stock transfers), config* (configurare), casademarcat/casamarcat (fiscal cash registers), obinvent (obiecte de inventar), stoc, rulaje, list*/rapoarte (reports), roagest.mnx/.mpr (the root startup menu, referenced by goApp.cStartupMenu).
  • todo.txt is an informal running work list (Romanian, ok/OK-prefixed = done, otherwise pending) — recent items concern store inventory (inventar magazin), FIFO stock cards, and VAT-rate handling during the 19%→21% transition; useful as a quick pulse on active/recent pain points but not authoritative documentation.
  • VAT/TVA is time-sensitive here too: recent changelog entries (v2.11.02.11.2) explicitly prepare the app for the 21%/11% rates effective 2025-08-01 while still supporting 19%/9%/5% for prior periods — the same "rate by document period, not 'current' rate" caution as the other ROA apps applies.
  • Cash register / fiscal integration: oproceduri_casademarcat.prg, oproceduri_casa_marcat_e500.prg, oproceduri_casa_marcat_mp500.prg (in COMUN/programe/) integrate specific fiscal printer/cash-register protocols (E500, MP500); Initializari/roagest_bon.xml/roagest_mp500.xml are their config templates.
  • ANAF e-Factura / SAFT: COMUN/programe/anaf_efactura.prg provides e-invoicing against ANAF, shared with sibling apps.

Changelog & release convention

changelog_roagest.txt is the user-facing release log (188KB, going back to v1.0.x). Newest entry goes at the top, in this exact HTML-comment block format (Romanian, DD/MM/YYYY):

<!--
21/01/2026
ROAGEST - 2.11.5

:nou:
  <what changed>

:modificare:
  <what changed>
-->

Tags in use: :nou: (new feature), :modificare: (change), :eroare: (bug fix), and occasionally :adaugare: (addition) — match this exact tag vocabulary (a lone historical :modfiicare: typo exists; don't repeat it). Bump the MAJOR.MINOR.PATCH version (currently 2.11.5) when you add an entry. The app checks for updates on startup (COMUN/programe/oupdate.prg, wwcodeupdate.prg) against versiune_db.txt's schema stamp; the runtime reads its own version from the built .exe's file version resource.

Intrările sunt simple și compacte — doar strictul necesar pentru utilizatori. O singură intrare consolidată per livrare (versiunea o dă Marius), fără pași intermediari, fără runde, fără mecanisme interne și fără erori apărute și corectate în interiorul aceleiași lucrări nelivrate.

Mod de lucru: delegare către subagenți + review înainte de commit

Preferințele lui Marius pentru sesiunile pe acest proiect:

  • Orchestrare pe misiuni lungi: niciodată un singur subagent care acumulează context pe multe sarcini înlănțuite — sesiunea principală orchestrează subagenți proaspeți per sarcină (prag: max ~200250k tokens per subagent, apoi handoff + agent nou), cu handoff compact pe disc; regula comună tuturor proiectelor ROA: COMUN\docs\orchestrare-subagenti.md.
  • Delegare: modificările de cod de volum/rutină (aplicarea unei propuneri din docs/propuneri_*.md, editări pe cache-ul text + write-back, actualizări de documentație, rulări de teste) se deleagă către subagenți Sonnet care lucrează în background (team agents — Agent tool cu model: sonnet, lane-uri paralele unde e posibil), iar sesiunea principală doar orchestrează și monitorizează: împarte planul pe lane-uri, transmite constatările între agenți, verifică rezultatele (diff, teste, fidelity) și intervine direct doar la deblocări (procese agățate), decizii și verificări.
  • Fără commit fără review: nu da commit din proprie inițiativă pe modificări de cod — Marius vrea întâi să vadă diff-ul. Pentru binarele VFP (.vcx/.scx), diff-ul lizibil se vede direct cu git diff pe textul .vc2/.sc2 din arbore (rulează întâi git_sync.ps1, ca textul să corespundă binarelor). Commit doar după ce Marius confirmă pe diff.
  • Curățenie înainte de commit: se rulează powershell -File COMUN\utile\curatenie.ps1 (-DryRun doar listează) — șterge patch-urile de review, handoff-urile/planurile de rundă, backup-urile *.pre_runda*.bak (proiect, COMUN, cache text) și artefactele de test (screenshots*/, uisync*/, *.fxp, *.err, loguri), sărind fișierele urmărite de git. Faptul că sunt în .gitignore nu le scutește: se șterg de pe disc. Abia apoi commit.

Stil de raspuns: scurt si concret

Marius vrea raspunsuri clare, concise, fara vorbarie. Regula, nu preferinta.

  • Starea si ce urmeaza, nu povestea. Ce e gata, ce e stricat, ce trebuie decis, ce urmeaza — in liste scurte, cu fisier si linie. Fara reconstituirea drumului pana la rezultat.
  • Fara naratiune de proces: ce a raportat fiecare agent, cine ce a corectat, cum au fost coordonate benzile. Intra in docs/, nu in raspuns.
  • Fara laude si fara reluari. Nu repeta ce s-a spus deja in conversatie.
  • Detaliile tehnice lungi (dovezi, iesiri de test, metodologie) se scriu in fisier si se trimite la el, nu se copiaza in raspuns.
  • Cand e ceva de decis: enunta decizia si optiunile in cateva randuri, cu recomandarea ta.

Reguli de lucru si testare

Inainte de orice modificare de cod sau testare, citeste COMUN\docs\reguli_lucru.md. Nu e optional si nu e doar context: contine regulile de livrare (diff ca fisier + aprobare inainte de write-back), comentariile (max o linie), modificarile minime, harnessul de testare headless si — la punctul 7 — lista de conventii obligatorii per zona atinsa (encoding cp1252 la editarea .vc2/.sc2, UX formulare/griduri, GO pe Recno(), goExecutor + ALTER TABLE, testare UI, export Oracle). Fisierul e index: urmeaza linkurile relevante pentru sarcina curenta. Depanare detaliata: COMUN\docs\depanare_testare_vfp.md.

Skill routing

When the user's request matches an available skill, invoke it via the Skill tool. When in doubt, invoke the skill.

Key routing rules:

  • Product ideas/brainstorming → invoke /office-hours
  • Strategy/scope → invoke /plan-ceo-review
  • Architecture → invoke /plan-eng-review
  • Design system/plan review → invoke /design-consultation or /plan-design-review
  • Full review pipeline → invoke /autoplan
  • Bugs/errors → invoke /investigate
  • QA/testing site behavior → invoke /qa or /qa-only
  • Code review/diff check → invoke /review
  • Visual polish → invoke /design-review
  • Ship/deploy/PR → invoke /ship or /land-and-deploy
  • Save progress → invoke /context-save
  • Resume context → invoke /context-restore

Project insights (docs/)

docs/ holds short, concrete notes discovered while working on real tasks — hidden flows, gotchas, key procedures/packages, relevant tables — that go beyond what this file covers. See docs/README.md for the index. Proactively offer to update docs/ whenever you uncover a non-obvious project insight while fixing a bug or investigating a flow (don't wait to be asked), so future sessions can reuse it instead of re-investigating from scratch. Keep entries concise and factual — no restating what's obvious from reading the code.