Claude Agent 3d212979d9 refactor(dashboard): move search box from filter bar to card header
Reduces vertical space by eliminating the second row in the filter bar.
Search input is now next to the "Comenzi" title, hidden on mobile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 14:04:10 +00:00
2025-08-26 22:59:58 +03:00
2026-03-16 18:18:45 +00:00
2026-03-05 11:54:29 +02:00
2026-03-16 18:18:45 +00:00
2026-03-16 17:56:09 +00:00

GoMag Vending - Import Comenzi Web → ROA Oracle

System automat de import comenzi din platforma GoMag in sistemul ERP ROA Oracle.

Arhitectura

[GoMag API] → [Python Sync Service] → [Oracle PL/SQL] → [FastAPI Admin]
     ↓                ↓                      ↑                  ↑
 JSON Orders    Download/Parse/Import    Store/Update    Dashboard + Config

Stack Tehnologic

  • API + Admin: FastAPI + Jinja2 + Bootstrap 5.3
  • GoMag Integration: Python (gomag_client.py — download comenzi cu paginare)
  • Sync Orchestrator: Python (sync_service.py — download → parse → validate → import)
  • Database: Oracle PL/SQL packages (IMPORT_PARTENERI, IMPORT_COMENZI) + SQLite (tracking)

Quick Start

Prerequisite

  • Python 3.10+
  • Oracle Instant Client 21.x (optional — suporta si thin mode pentru Oracle 12.1+)

Instalare

pip install -r api/requirements.txt
cp api/.env.example api/.env
# Editeaza api/.env cu datele de conectare Oracle

Pornire server

Important: serverul trebuie pornit din project root, nu din api/:

python -m uvicorn api.app.main:app --host 0.0.0.0 --port 5003

Sau folosind scriptul inclus:

./start.sh

Deschide http://localhost:5003 in browser.

Testare

Test A - Basic (fara Oracle):

python api/test_app_basic.py

Test C - Integrare Oracle:

python api/test_integration.py

Configurare (.env)

Copiaza .env.example si completeaza:

cp api/.env.example api/.env
Variabila Descriere Exemplu
ORACLE_USER User Oracle MARIUSM_AUTO
ORACLE_PASSWORD Parola Oracle secret
ORACLE_DSN TNS alias ROA_CENTRAL
TNS_ADMIN Cale absoluta la tnsnames.ora /mnt/e/.../gomag/api
INSTANTCLIENTPATH Cale Instant Client (thick mode) /opt/oracle/instantclient_21_15
FORCE_THIN_MODE Thin mode fara Instant Client true
SQLITE_DB_PATH Path SQLite (relativ la project root) api/data/import.db
JSON_OUTPUT_DIR Folder JSON-uri descarcate api/data/orders
APP_PORT Port HTTP 5003
ID_POL ID Politica ROA 39
ID_GESTIUNE ID Gestiune ROA 0
ID_SECTIE ID Sectie ROA 6

Nota Oracle mode:

  • Thick mode (Oracle 10g/11g): seteaza INSTANTCLIENTPATH
  • Thin mode (Oracle 12.1+): seteaza FORCE_THIN_MODE=true, sterge INSTANTCLIENTPATH

Structura Proiect

gomag-vending/
├── api/                          # FastAPI Admin + Dashboard
│   ├── app/
│   │   ├── main.py              # Entry point, lifespan, logging
│   │   ├── config.py            # Settings (pydantic-settings + .env)
│   │   ├── database.py          # Oracle pool + SQLite schema + migrari
│   │   ├── routers/             # Endpoint-uri HTTP
│   │   │   ├── health.py        # GET /health
│   │   │   ├── dashboard.py     # GET / (HTML)
│   │   │   ├── mappings.py      # /mappings, /api/mappings
│   │   │   ├── articles.py      # /api/articles/search
│   │   │   ├── validation.py    # /api/validate/*
│   │   │   └── sync.py          # /api/sync/* + /api/dashboard/orders
│   │   ├── services/
│   │   │   ├── gomag_client.py      # Download comenzi GoMag API
│   │   │   ├── sync_service.py      # Orchestrare: download→validate→import
│   │   │   ├── import_service.py    # Import comanda in Oracle ROA
│   │   │   ├── mapping_service.py   # CRUD ARTICOLE_TERTI + pct_total
│   │   │   ├── sqlite_service.py    # Tracking runs/orders/missing SKUs
│   │   │   ├── order_reader.py      # Citire gomag_orders_page*.json
│   │   │   ├── validation_service.py
│   │   │   ├── article_service.py
│   │   │   ├── invoice_service.py   # Verificare facturi ROA
│   │   │   └── scheduler_service.py # APScheduler timer
│   │   ├── templates/           # Jinja2 HTML
│   │   └── static/              # CSS + JS
│   ├── database-scripts/        # Oracle SQL (ARTICOLE_TERTI, packages)
│   ├── data/                    # SQLite DB (import.db) + JSON orders
│   ├── .env                     # Configurare locala (nu in git)
│   ├── .env.example             # Template configurare
│   ├── test_app_basic.py        # Test A - fara Oracle
│   ├── test_integration.py      # Test C - cu Oracle
│   └── requirements.txt
├── logs/                        # Log-uri aplicatie (sync_comenzi_*.log)
├── docs/                        # Documentatie (PRD, stories)
├── screenshots/                 # Before/preview/after pentru UI changes
├── start.sh                     # Script pornire (Linux/WSL)
└── CLAUDE.md                    # Instructiuni pentru AI assistants

Dashboard Features

Sync Panel

  • Start sync manual sau scheduler automat (5/10/30 min)
  • Progress live: "Import 45/80: #CMD-1234 Ion Popescu"
  • Smart polling: 30s idle → 3s cand ruleaza → auto-refresh tabela
  • Last sync clickabil → jurnal detaliat

Comenzi

  • Filtru perioada: 3z / 7z / 30z / 3 luni / toate / custom
  • Status pills cu conturi totale pe perioada (nu per-pagina)
  • Cautare integrata in bara de filtre
  • Coloana Client cu tooltip cand persoana livrare ≠ facturare
  • Paginare sus + jos, selector rezultate per pagina (25/50/100/250)

Mapari SKU

  • Badge ✓ 100% / ⚠ 80% per grup SKU
  • Filtru Complete / Incomplete
  • Verificare duplicat SKU-CODMAT (409 cu optiune de restaurare)

SKU-uri Lipsa

  • Cautare dupa SKU sau nume produs
  • Filtru Nerezolvate / Rezolvate / Toate cu conturi
  • Re-scan cu progress inline si banner rezultat

Fluxul de Import

1. gomag_client.py descarca comenzi GoMag API → JSON files
2. order_reader.py parseaza JSON-urile
3. validation_service.py valideaza SKU-uri contra ARTICOLE_TERTI + NOM_ARTICOLE
4. import_service.py creeaza/cauta partener in Oracle (shipping person = facturare)
5. PACK_IMPORT_COMENZI.importa_comanda_web() insereaza comanda in ROA
6. Rezultate salvate in SQLite (orders, sync_run_orders, order_items)

Statuses Comenzi

Status Descriere
IMPORTED Importata nou in ROA in acest run
ALREADY_IMPORTED Existenta deja in Oracle, contorizata
SKIPPED SKU-uri lipsa → neimportata
ERROR Eroare la import
DELETED_IN_ROA A fost importata dar comanda a fost stearsa din ROA

Regula upsert: daca statusul existent este IMPORTED, nu se suprascrie cu ALREADY_IMPORTED.

Reguli Business

  • Persoana: shipping name = persoana pe eticheta = beneficiarul facturii
  • Adresa: cand billing ≠ shipping → adresa shipping pentru ambele (facturare + livrare)
  • SKU simplu: gasit direct in NOM_ARTICOLE → nu se stocheaza in ARTICOLE_TERTI
  • SKU cu repackaging: un SKU → CODMAT cu cantitate diferita
  • SKU set complex: un SKU → multiple CODMAT-uri cu procente de pret

Facturi & Cache

Facturile sunt verificate live din Oracle si cacate in SQLite (factura_* pe tabelul orders).

Sursa Oracle

SELECT id_comanda, numar_act, serie_act,
       total_fara_tva, total_tva, total_cu_tva,
       TO_CHAR(data_act, 'YYYY-MM-DD')
FROM vanzari
WHERE id_comanda IN (...) AND sters = 0

Populare Cache

  1. Dashboard (GET /api/dashboard/orders) — comenzile fara cache sunt verificate live si cacate automat la fiecare request
  2. Detaliu comanda (GET /api/sync/order/{order_number}) — verifica Oracle live daca nu e caat
  3. Refresh manual (POST /api/dashboard/refresh-invoices) — refresh complet pentru toate comenzile

Refresh Complet — /api/dashboard/refresh-invoices

Face trei verificari in Oracle si actualizeaza SQLite:

Verificare Actiune
Comenzi necacturate → au primit factura? Cacheaza datele facturii
Comenzi cacturate → factura a fost stearsa? Sterge cache factura
Toate comenzile importate → comanda stearsa din ROA? Seteaza status DELETED_IN_ROA

Returneaza: { checked, invoices_added, invoices_cleared, orders_deleted }


API Reference — Sync & Comenzi

Sync

Method Path Descriere
POST /api/sync/start Porneste sync in background
POST /api/sync/stop Trimite semnal de stop
GET /api/sync/status Status curent + progres + last_run
GET /api/sync/history Istoric run-uri (paginat)
GET /api/sync/run/{id} Detalii run specific
GET /api/sync/run/{id}/log Log per comanda (JSON)
GET /api/sync/run/{id}/text-log Log text (live din memorie sau reconstruit din SQLite)
GET /api/sync/run/{id}/orders Comenzi run filtrate/paginate
GET /api/sync/order/{number} Detaliu comanda + items + ARTICOLE_TERTI + factura

Dashboard Comenzi

Method Path Descriere
GET /api/dashboard/orders Comenzi cu enrichment factura
POST /api/dashboard/refresh-invoices Force-refresh stare facturi + deleted orders

Parametri /api/dashboard/orders:

  • period_days: 3/7/30/90 sau 0 (toate sau interval custom)
  • period_start, period_end: interval custom (cand period_days=0)
  • status: all / IMPORTED / SKIPPED / ERROR / UNINVOICED / INVOICED
  • search, sort_by, sort_dir, page, per_page

Filtrele UNINVOICED si INVOICED fac fetch din toate comenzile IMPORTED si filtreaza server-side dupa prezenta/absenta cache-ului de factura.

Scheduler

Method Path Descriere
PUT /api/sync/schedule Configureaza (enabled, interval_minutes: 5/10/30)
GET /api/sync/schedule Status curent

Configuratia este persistata in SQLite (scheduler_config).

Settings

Method Path Descriere
GET /api/settings Citeste setari aplicatie
PUT /api/settings Salveaza setari
GET /api/settings/sectii Lista sectii Oracle
GET /api/settings/politici Lista politici preturi Oracle

Setari disponibile: transport_codmat, transport_vat, discount_codmat, discount_vat, transport_id_pol, discount_id_pol, id_pol, id_sectie, gomag_api_key, gomag_api_shop, gomag_order_days_back, gomag_limit


Status Implementare

Faza Status Descriere
Phase 1: Database Foundation Complet ARTICOLE_TERTI, PACK_IMPORT_PARTENERI, PACK_IMPORT_COMENZI
Phase 2: Python Integration Complet gomag_client.py, sync_service.py
Phase 3-4: FastAPI Dashboard Complet UI responsive, smart polling, filter bar, paginare
Phase 5: Production In Progress Logging done, Auth + SMTP pending

Deploy Windows

Instalare initiala

# Ruleaza ca Administrator
.\deploy.ps1

Scriptul deploy.ps1 face automat: git clone, venv, dependinte, detectare Oracle, start.bat, serviciu NSSM, configurare IIS reverse proxy.

Update cod (pull + restart)

# Ca Administrator
.\update.ps1

Sau manual:

cd C:\gomag-vending
git pull origin main
nssm restart GoMagVending

Configurare .env pe Windows

# api/.env — exemplu Windows
ORACLE_USER=VENDING
ORACLE_PASSWORD=****
ORACLE_DSN=ROA
TNS_ADMIN=C:\roa\instantclient_11_2_0_2
INSTANTCLIENTPATH=C:\app\Server\product\18.0.0\dbhomeXE\bin
SQLITE_DB_PATH=api/data/import.db
JSON_OUTPUT_DIR=api/data/orders
APP_PORT=5003
ID_POL=39
ID_GESTIUNE=0
ID_SECTIE=6
GOMAG_API_KEY=...
GOMAG_API_SHOP=...
GOMAG_ORDER_DAYS_BACK=7
GOMAG_LIMIT=100

Important:

  • TNS_ADMIN = folderul care contine tnsnames.ora (NU fisierul in sine)
  • ORACLE_DSN = alias-ul exact din tnsnames.ora
  • INSTANTCLIENTPATH = calea catre Oracle bin (thick mode, Oracle 10g/11g)
  • FORCE_THIN_MODE=true = elimina necesitatea Instant Client (Oracle 12.1+)
  • Setarile din .env pot fi suprascrise din UI → Setari → salvate in SQLite

Serviciu Windows (NSSM)

nssm restart GoMagVending    # restart serviciu
nssm status GoMagVending     # status serviciu
nssm stop GoMagVending       # stop serviciu
nssm start GoMagVending      # start serviciu

Loguri serviciu: logs/service_stdout.log, logs/service_stderr.log Loguri aplicatie: logs/sync_comenzi_*.log

Nota: Userul gomag nu are drepturi de admin — nssm restart necesita PowerShell Administrator direct pe server.

Depanare SSH

# Conectare SSH (PowerShell remote, cheie publica)
ssh -p 22122 gomag@79.119.86.134

# Verificare .env
cmd /c type C:\gomag-vending\api\.env

# Test conexiune Oracle
C:\gomag-vending\venv\Scripts\python.exe -c "import oracledb, os; os.environ['TNS_ADMIN']='C:/roa/instantclient_11_2_0_2'; conn=oracledb.connect(user='VENDING', password='ROMFASTSOFT', dsn='ROA'); print('Connected!'); conn.close()"

# Verificare tnsnames.ora
cmd /c type C:\roa\instantclient_11_2_0_2\tnsnames.ora

# Verificare procese Python
Get-Process *python* | Select-Object Id,ProcessName,Path

# Verificare loguri recente
Get-ChildItem C:\gomag-vending\logs\*.log | Sort-Object LastWriteTime -Descending | Select-Object -First 3

# Test sync manual (verifica ca Oracle pool porneste)
curl http://localhost:5003/health
curl -X POST http://localhost:5003/api/sync/start

# Refresh facturi manual
curl -X POST http://localhost:5003/api/dashboard/refresh-invoices

Probleme frecvente

Eroare Cauza Solutie
ORA-12154: TNS:could not resolve TNS_ADMIN gresit sau tnsnames.ora nu contine alias-ul DSN Verifica TNS_ADMIN in .env + alias in tnsnames.ora
ORA-04088: LOGON_AUDIT_TRIGGER + Nu aveti licenta pentru PYTHON Trigger ROA blocheaza executabile nelicențiate Adauga python.exe (calea completa) in ROASUPORT
503 Service Unavailable pe /api/articles/search Oracle pool nu s-a initializat Verifica logul sync_comenzi_*.log pentru eroarea exacta
Facturile nu apar in dashboard Cache SQLite gol — invoice_service nu a putut interoga Oracle Apasa butonul Refresh Facturi din dashboard sau POST /api/dashboard/refresh-invoices
Comanda apare ca DELETED_IN_ROA Comanda a fost stearsa manual din ROA Normal — marcat automat la refresh
Scheduler nu porneste dupa restart Config pierduta Verifica SQLite scheduler_config sau reconfigureaza din UI

WSL2 Note

  • uvicorn --reload nu functioneaza pe /mnt/e/ (WSL2 limitation) — restarta manual
  • Serverul trebuie pornit din project root, nu din api/
  • JSON_OUTPUT_DIR si SQLITE_DB_PATH sunt relative la project root
Description
No description provided
Readme 3.6 MiB
Languages
PLSQL 63.8%
Python 23.4%
JavaScript 6.4%
HTML 2.9%
PowerShell 1.4%
Other 2%