docs: update README and .env.example for project root start convention
Fix start command (python -m uvicorn api.app.main:app from project root), correct JSON_OUTPUT_DIR path (vfp/output not ../vfp/output), document all env variables with descriptions, add dashboard features overview, business rules, and WSL2 notes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
210
README.md
210
README.md
@@ -16,18 +16,35 @@ System automat de import comenzi din platforma GoMag in sistemul ERP ROA Oracle.
|
|||||||
- **Admin/Dashboard:** FastAPI + Jinja2 + Oracle pool + SQLite
|
- **Admin/Dashboard:** FastAPI + Jinja2 + Oracle pool + SQLite
|
||||||
- **Date:** Oracle 11g/12c (schema ROA), SQLite (tracking local)
|
- **Date:** Oracle 11g/12c (schema ROA), SQLite (tracking local)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Prerequisite
|
### Prerequisite
|
||||||
- Python 3.10+
|
- Python 3.10+
|
||||||
- Oracle Instant Client (optional - suporta si thin mode)
|
- Oracle Instant Client 21.x (optional — suporta si thin mode pentru Oracle 12.1+)
|
||||||
|
|
||||||
|
### Instalare
|
||||||
|
|
||||||
### Instalare si pornire
|
|
||||||
```bash
|
```bash
|
||||||
cd api
|
# Din project root (gomag/)
|
||||||
pip install -r requirements.txt
|
pip install -r api/requirements.txt
|
||||||
# Configureaza .env (vezi api/.env.example)
|
cp api/.env.example api/.env
|
||||||
uvicorn app.main:app --host 0.0.0.0 --port 5003 --reload
|
# Editeaza api/.env cu datele de conectare Oracle
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pornire server
|
||||||
|
|
||||||
|
**Important:** serverul trebuie pornit **din project root**, nu din `api/`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Din gomag/
|
||||||
|
python -m uvicorn api.app.main:app --host 0.0.0.0 --port 5003
|
||||||
|
```
|
||||||
|
|
||||||
|
Sau folosind scriptul inclus:
|
||||||
|
```bash
|
||||||
|
./start.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Deschide `http://localhost:5003` in browser.
|
Deschide `http://localhost:5003` in browser.
|
||||||
@@ -36,93 +53,154 @@ Deschide `http://localhost:5003` in browser.
|
|||||||
|
|
||||||
**Test A - Basic (fara Oracle):**
|
**Test A - Basic (fara Oracle):**
|
||||||
```bash
|
```bash
|
||||||
cd api
|
python api/test_app_basic.py
|
||||||
python test_app_basic.py
|
|
||||||
```
|
```
|
||||||
Verifica 17 importuri de module + 13 rute GET. Asteptat: 30/30 PASS.
|
Verifica importuri de module + rute GET. Asteptat: 32/33 PASS (1 fail pre-existent `/sync` HTML).
|
||||||
|
|
||||||
**Test C - Integrare Oracle:**
|
**Test C - Integrare Oracle:**
|
||||||
```bash
|
```bash
|
||||||
python api/test_integration.py
|
python api/test_integration.py
|
||||||
```
|
```
|
||||||
Necesita Oracle activ. Verifica health, mappings CRUD, article search, validation, sync. Asteptat: 9/9 PASS.
|
Necesita Oracle activ. Verifica health, mappings CRUD, article search, validation, sync.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configurare (.env)
|
||||||
|
|
||||||
|
Copiaza `.env.example` si completeaza:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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 VFP (relativ la project root) | `vfp/output` |
|
||||||
|
| `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
|
## Structura Proiect
|
||||||
|
|
||||||
```
|
```
|
||||||
/
|
gomag/
|
||||||
├── api/ # FastAPI Admin + Database
|
├── api/ # FastAPI Admin + Dashboard
|
||||||
│ ├── app/ # Aplicatia FastAPI
|
│ ├── app/
|
||||||
│ │ ├── main.py # Entry point, lifespan, logging
|
│ │ ├── main.py # Entry point, lifespan, logging
|
||||||
│ │ ├── config.py # Settings (pydantic-settings, .env)
|
│ │ ├── config.py # Settings (pydantic-settings + .env)
|
||||||
│ │ ├── database.py # Oracle pool + SQLite init
|
│ │ ├── database.py # Oracle pool + SQLite schema + migrari
|
||||||
│ │ ├── routers/ # Endpoint-uri HTTP
|
│ │ ├── routers/ # Endpoint-uri HTTP
|
||||||
│ │ │ ├── health.py # /health, /api/health
|
│ │ │ ├── health.py # GET /health
|
||||||
│ │ │ ├── dashboard.py # / (dashboard HTML)
|
│ │ │ ├── dashboard.py # GET / (HTML)
|
||||||
│ │ │ ├── mappings.py # /mappings, /api/mappings
|
│ │ │ ├── mappings.py # /mappings, /api/mappings
|
||||||
│ │ │ ├── articles.py # /api/articles/search
|
│ │ │ ├── articles.py # /api/articles/search
|
||||||
│ │ │ ├── validation.py # /api/validate/*
|
│ │ │ ├── validation.py # /api/validate/*
|
||||||
│ │ │ └── sync.py # /api/sync/*
|
│ │ │ └── sync.py # /api/sync/* + /api/dashboard/orders
|
||||||
│ │ ├── services/ # Business logic
|
│ │ ├── services/
|
||||||
│ │ │ ├── mapping_service # CRUD ARTICOLE_TERTI
|
│ │ │ ├── sync_service.py # Orchestrare: JSON→validate→import
|
||||||
│ │ │ ├── article_service # Cautare NOM_ARTICOLE
|
│ │ │ ├── import_service.py # Import comanda in Oracle ROA
|
||||||
│ │ │ ├── import_service # Import comanda in Oracle
|
│ │ │ ├── mapping_service.py # CRUD ARTICOLE_TERTI + pct_total
|
||||||
│ │ │ ├── sync_service # Orchestrare: JSON→validate→import
|
│ │ │ ├── sqlite_service.py # Tracking runs/orders/missing SKUs
|
||||||
│ │ │ ├── validation_service # Validare SKU-uri
|
│ │ │ ├── order_reader.py # Citire gomag_orders_page*.json
|
||||||
│ │ │ ├── order_reader # Citire JSON-uri din vfp/output/
|
│ │ │ ├── validation_service.py
|
||||||
│ │ │ ├── sqlite_service # Tracking runs/orders/missing SKUs
|
│ │ │ ├── article_service.py
|
||||||
│ │ │ └── scheduler_service # APScheduler timer
|
│ │ │ └── scheduler_service.py # APScheduler timer
|
||||||
│ │ ├── templates/ # Jinja2 HTML (dashboard, mappings, etc.)
|
│ │ ├── templates/ # Jinja2 HTML
|
||||||
│ │ └── static/ # CSS + JS
|
│ │ └── static/ # CSS + JS
|
||||||
│ ├── database-scripts/ # Oracle SQL scripts
|
│ ├── database-scripts/ # Oracle SQL (ARTICOLE_TERTI, packages)
|
||||||
|
│ ├── data/ # SQLite DB (import.db)
|
||||||
|
│ ├── .env # Configurare locala (nu in git)
|
||||||
|
│ ├── .env.example # Template configurare
|
||||||
│ ├── test_app_basic.py # Test A - fara Oracle
|
│ ├── test_app_basic.py # Test A - fara Oracle
|
||||||
│ ├── test_integration.py # Test C - cu Oracle
|
│ ├── test_integration.py # Test C - cu Oracle
|
||||||
│ └── requirements.txt # Python dependencies
|
│ └── requirements.txt
|
||||||
├── vfp/ # VFP Integration
|
├── vfp/ # VFP Integration
|
||||||
│ ├── gomag-vending.prg # Client GoMag API
|
│ ├── gomag-vending.prg # Client GoMag API (descarca JSON-uri)
|
||||||
│ ├── sync-comenzi-web.prg # Orchestrator VFP
|
│ ├── sync-comenzi-web.prg # Orchestrator VFP
|
||||||
│ └── utils.prg # Utilitare VFP
|
│ ├── utils.prg # Utilitare (log, settings, connectivity)
|
||||||
├── docs/ # Documentatie
|
│ └── output/ # JSON-uri descarcate (gomag_orders_page*.json)
|
||||||
│ ├── PRD.md # Product Requirements
|
├── logs/ # Log-uri aplicatie (sync_comenzi_*.log)
|
||||||
│ └── stories/ # User Stories
|
├── docs/ # Documentatie (PRD, stories)
|
||||||
└── logs/ # Log-uri aplicatie
|
├── start.sh # Script pornire (Linux/WSL)
|
||||||
|
└── CLAUDE.md # Instructiuni pentru AI assistants
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configurare (.env)
|
---
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
```env
|
|
||||||
ORACLE_USER=MARIUSM_AUTO
|
|
||||||
ORACLE_PASSWORD=********
|
|
||||||
ORACLE_DSN=ROA_CENTRAL
|
|
||||||
FORCE_THIN_MODE=true # sau INSTANTCLIENTPATH=C:\oracle\instantclient
|
|
||||||
SQLITE_DB_PATH=data/import.db
|
|
||||||
APP_PORT=5003
|
|
||||||
LOG_LEVEL=INFO
|
|
||||||
JSON_OUTPUT_DIR=../vfp/output
|
|
||||||
```
|
```
|
||||||
|
1. VFP descarca comenzi GoMag API → vfp/output/gomag_orders_page*.json
|
||||||
|
2. FastAPI citeste JSON-urile (order_reader)
|
||||||
|
3. Valideaza SKU-uri contra ARTICOLE_TERTI + NOM_ARTICOLE (validation_service)
|
||||||
|
4. Import_service 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)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Status Implementare
|
## Status Implementare
|
||||||
|
|
||||||
### Phase 1: Database Foundation - COMPLET
|
| Faza | Status | Descriere |
|
||||||
- ARTICOLE_TERTI table + Docker setup
|
|------|--------|-----------|
|
||||||
- PACK_IMPORT_PARTENERI package
|
| Phase 1: Database Foundation | ✅ Complet | ARTICOLE_TERTI, PACK_IMPORT_PARTENERI, PACK_IMPORT_COMENZI |
|
||||||
- PACK_IMPORT_COMENZI package
|
| Phase 2: VFP Integration | ✅ Complet | gomag-vending.prg, sync-comenzi-web.prg |
|
||||||
|
| Phase 3-4: FastAPI Dashboard | ✅ Complet | Redesign UI, smart polling, filter bar, paginare, tooltip |
|
||||||
|
| Phase 5: Production | 🔄 In Progress | Logging ✅, Auth ⏳, SMTP ⏳, NSSM service ⏳ |
|
||||||
|
|
||||||
### Phase 2: VFP Integration - COMPLET
|
---
|
||||||
- gomag-vending.prg (GoMag API client)
|
|
||||||
- sync-comenzi-web.prg (orchestrator cu logging)
|
|
||||||
|
|
||||||
### Phase 3-4: FastAPI Admin + Dashboard - COMPLET
|
## WSL2 Note
|
||||||
- Mappings CRUD + CSV import/export
|
|
||||||
- Article autocomplete (NOM_ARTICOLE)
|
|
||||||
- Pre-validation SKU-uri
|
|
||||||
- Import orchestration (JSON→Oracle)
|
|
||||||
- Dashboard cu stat cards, sync control, history
|
|
||||||
- Missing SKUs management page
|
|
||||||
- File logging (logs/sync_comenzi_*.log)
|
|
||||||
|
|
||||||
### Phase 5: Production - IN PROGRESS
|
- `uvicorn --reload` **nu functioneaza** pe `/mnt/e/` (WSL2 limitation) — restarta manual
|
||||||
- [x] File logging
|
- Serverul trebuie pornit din **project root** (`gomag/`), nu din `api/`
|
||||||
- [ ] Email notifications (SMTP)
|
- `JSON_OUTPUT_DIR` si `SQLITE_DB_PATH` sunt relative la project root
|
||||||
- [ ] HTTP Basic Auth
|
|
||||||
- [ ] NSSM Windows service
|
|
||||||
|
|||||||
@@ -1,15 +1,75 @@
|
|||||||
# Oracle Database Configuration
|
# =============================================================================
|
||||||
ORACLE_USER=YOUR_ORACLE_USERNAME
|
# GoMag Import Manager - Configurare
|
||||||
ORACLE_PASSWORD=YOUR_ORACLE_PASSWORD
|
# Copiaza in api/.env si completeaza cu datele reale
|
||||||
ORACLE_DSN=YOUR_TNS_CONNECTION_NAME
|
# =============================================================================
|
||||||
TNS_ADMIN=/app
|
|
||||||
INSTANTCLIENTPATH=/opt/oracle/instantclient_21_1
|
|
||||||
|
|
||||||
# Flask Configuration
|
# =============================================================================
|
||||||
FLASK_ENV=development
|
# ORACLE MODE - Alege una din urmatoarele doua optiuni:
|
||||||
FLASK_DEBUG=1
|
# =============================================================================
|
||||||
PYTHONUNBUFFERED=1
|
|
||||||
|
|
||||||
# Application Settings
|
# THICK MODE (Oracle 10g/11g/12.1+) - Recomandat pentru compatibilitate maxima
|
||||||
APP_PORT=5000
|
# Necesita Oracle Instant Client instalat
|
||||||
LOG_LEVEL=DEBUG
|
INSTANTCLIENTPATH=/opt/oracle/instantclient_21_15
|
||||||
|
|
||||||
|
# THIN MODE (Oracle 12.1+ only) - Fara Instant Client, mai simplu
|
||||||
|
# Comenteaza INSTANTCLIENTPATH de sus si decommenteaza urmatoarea linie:
|
||||||
|
# FORCE_THIN_MODE=true
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ORACLE - Credentiale baza de date
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
ORACLE_USER=USER_ORACLE
|
||||||
|
ORACLE_PASSWORD=parola_oracle
|
||||||
|
ORACLE_DSN=TNS_ALIAS
|
||||||
|
|
||||||
|
# Calea absoluta la directorul cu tnsnames.ora
|
||||||
|
# De obicei: directorul api/ al proiectului
|
||||||
|
TNS_ADMIN=/cale/absoluta/la/gomag/api
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# APLICATIE
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
APP_PORT=5003
|
||||||
|
LOG_LEVEL=INFO
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# CALE FISIERE (relative la project root - directorul gomag/)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# JSON-uri descarcate de VFP
|
||||||
|
JSON_OUTPUT_DIR=vfp/output
|
||||||
|
|
||||||
|
# SQLite tracking DB
|
||||||
|
SQLITE_DB_PATH=api/data/import.db
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ROA - Setari import comenzi (din vfp/settings.ini sectiunea [ROA])
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Politica de pret
|
||||||
|
ID_POL=39
|
||||||
|
|
||||||
|
# Gestiune implicita
|
||||||
|
ID_GESTIUNE=0
|
||||||
|
|
||||||
|
# Sectie implicita
|
||||||
|
ID_SECTIE=6
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# SMTP - Notificari email (optional)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# SMTP_HOST=smtp.gmail.com
|
||||||
|
# SMTP_PORT=587
|
||||||
|
# SMTP_USER=email@exemplu.com
|
||||||
|
# SMTP_PASSWORD=parola_app
|
||||||
|
# SMTP_TO=destinatar@exemplu.com
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# AUTH - HTTP Basic Auth pentru dashboard (optional)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# API_USERNAME=admin
|
||||||
|
# API_PASSWORD=parola_sigura
|
||||||
|
|||||||
Reference in New Issue
Block a user