Complete implementation of multi-server Oracle database support: Backend: - Multi-pool Oracle with lazy loading per server - Email-to-server cache for automatic server discovery - JWT tokens include server_id claim - /auth/check-identity and /auth/check-email endpoints - /auth/my-servers endpoint for listing user's accessible servers - Server switch with password re-authentication Frontend: - New ServerSelector component for header dropdown - Multi-step login flow (identity → server → password) - Server switching from header with password modal - Mobile drawer menu with server selection - Dark mode support for all new components - URL bookmark support with ?server= query param Scripts: - Unified start.sh replacing start-prod.sh/start-test.sh - Unified ssh-tunnel.sh with multi-server support - Updated status.sh for new architecture Tests: - E2E tests for multi-server and single-server login flows - Backend unit tests for all new endpoints - Oracle multi-pool integration tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
216 lines
7.8 KiB
Markdown
216 lines
7.8 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
**ROA2WEB** - Modern ERP Application with ultrathin monolith architecture:
|
|
- **Reports Module** (`backend/modules/reports/`) - Read-only reports from Oracle
|
|
- **Data Entry Module** (`backend/modules/data_entry/`) - Data input with approval workflow
|
|
- **Telegram Bot Module** (`backend/modules/telegram/`) - Telegram bot integration
|
|
|
|
**Main Branch**: `main` | **Setup & Commands**: See `README.md`
|
|
|
|
---
|
|
|
|
## Module-Specific Instructions
|
|
|
|
> **IMPORTANT**: Read module documentation FIRST before working on a module!
|
|
|
|
| Module | Documentation | Key Points |
|
|
|--------|--------------|------------|
|
|
| **Data Entry** | `docs/data-entry/DATA-ENTRY-MODULE.md` | SQLModel, SQLite, workflow states |
|
|
| **Reports** | This file + `README.md` | Oracle read-only, caching |
|
|
| **Telegram** | `docs/telegram/README.md` | Bot commands, formatting |
|
|
|
|
---
|
|
|
|
## Quick Reference
|
|
|
|
### Architecture
|
|
See `docs/ARCHITECTURE-DECISIONS.md` for:
|
|
- Single worker (`--workers 1`) - required for Telegram bot
|
|
- Ultrathin monolith rationale
|
|
- IIS deployment strategy
|
|
|
|
### Starting Services
|
|
```bash
|
|
./start.sh prod # Backend :8000 + Frontend :3000 (PROD)
|
|
./start.sh prod stop # Stop all services
|
|
./start.sh test # Start in TEST mode
|
|
./start.sh test stop # Stop TEST services
|
|
./ssh-tunnel.sh # Oracle DB tunnel (for servers with SSH access)
|
|
./status.sh # Check services
|
|
```
|
|
|
|
### Playwright Testing
|
|
```bash
|
|
# Pentru testare UI cu Playwright:
|
|
./start.sh test # Pornește în mod TEST
|
|
./start.sh test stop # Oprește serverele
|
|
|
|
# Credențiale TEST:
|
|
# User: MARIUS M
|
|
# Pass: 123
|
|
# Firma: MARIUSM AUTO
|
|
```
|
|
|
|
### Database
|
|
- **Schema**: `CONTAFIN_ORACLE`
|
|
- **Connection**: SSH tunnel required (Linux dev)
|
|
- **Env**: `backend/.env` (see `backend/ENV-SETUP.md`)
|
|
|
|
---
|
|
|
|
## Key Rules (ALWAYS FOLLOW)
|
|
|
|
### Git Commits
|
|
- **NU da commit automat!** Întreabă utilizatorul ÎNAINTE de a face commit
|
|
- Arată ce fișiere s-au modificat (`git status`) și propune mesajul de commit
|
|
- Așteaptă confirmarea explicită înainte de `git commit`
|
|
|
|
### Frontend Development
|
|
**Before writing CSS**: Read `docs/ONBOARDING_CSS.md` (5 min)
|
|
|
|
#### CSS Design Tokens - OBLIGATORIU ⚠️
|
|
- **CITEȘTE ÎNTÂI**: `docs/DESIGN_TOKENS.md` înainte de a scrie CSS
|
|
- Folosește **DOAR** design tokens, NICIODATĂ valori hardcodate:
|
|
- Spacing: `var(--space-xs)` (4px), `var(--space-sm)` (8px), `var(--space-md)` (16px)
|
|
- Font weight: `var(--font-medium)` (500), `var(--font-semibold)` (600), `var(--font-bold)` (700)
|
|
- Colors: `var(--green-50)`, `var(--blue-50)`, `var(--surface-card)`, etc.
|
|
- Radius: `var(--radius-sm)` (4px), `var(--radius-md)` (8px)
|
|
- ❌ GREȘIT: `padding: 8px`, `font-weight: 500`, `background: #f0fdf4`
|
|
- ✅ CORECT: `padding: var(--space-sm)`, `font-weight: var(--font-medium)`, `background: var(--green-50)`
|
|
|
|
#### Alte reguli CSS
|
|
- Use shared CSS from `src/assets/css/` - NEVER duplicate
|
|
- Check `docs/CSS_PATTERNS.md` for existing patterns
|
|
- **Theme toggle**: App has 3 modes (auto/light/dark) - test BOTH themes!
|
|
|
|
**Tables**:
|
|
- Use separate columns (Debit | Credit, not stacked)
|
|
- Filter buttons on separate row below filters
|
|
- Export ALL data, not just current page
|
|
|
|
### Mobile Development Rules ⚠️
|
|
|
|
**Before writing mobile UI**: Read `docs/MOBILE_PATTERNS.md`
|
|
|
|
#### Required Components
|
|
All mobile pages **MUST** use these shared components:
|
|
- **MobileTopBar**: Required for all mobile views (title, actions, back navigation)
|
|
- **MobileBottomNav**: Required for all mobile views (persistent navigation)
|
|
- **BottomSheet**: Required for filters on mobile (NEVER inline filters)
|
|
- **MobileSelectionFooter**: Required when items are selectable (batch actions)
|
|
|
|
```javascript
|
|
// Import from shared components
|
|
import MobileTopBar from '@shared/components/mobile/MobileTopBar.vue'
|
|
import MobileBottomNav from '@shared/components/mobile/MobileBottomNav.vue'
|
|
import BottomSheet from '@shared/components/mobile/BottomSheet.vue'
|
|
import MobileSelectionFooter from '@shared/components/mobile/MobileSelectionFooter.vue'
|
|
```
|
|
|
|
#### Layout Rules
|
|
1. **Filters → BottomSheet**: Pe mobil, filtrele se pun ÎNTOTDEAUNA în BottomSheet, NU inline
|
|
2. **Selection Actions → Footer**: Când sunt elemente selectate, acțiunile apar în MobileSelectionFooter, NU în header
|
|
3. **Touch Targets**: Minimum **44x44px** pentru toate elementele interactive (butoane, linkuri, checkbox-uri)
|
|
4. **Content Padding**: Conținutul trebuie să aibă `padding-top: 56px` și `padding-bottom: 56px` pentru barele fixe
|
|
|
|
#### Mobile Code Review Checklist ✓
|
|
|
|
```markdown
|
|
□ Folosește MobileTopBar cu props corecte (title, showBack/showMenu, actions)
|
|
□ Folosește MobileBottomNav pentru navigare
|
|
□ Filtrele sunt în BottomSheet (nu inline pe pagină)
|
|
□ Selecția afișează MobileSelectionFooter (nu butoane în header)
|
|
□ Touch targets ≥ 44x44px
|
|
□ Padding pentru bare fixe (top: 56px, bottom: 56px)
|
|
□ Testat în dark mode
|
|
□ Folosește design tokens (nu valori hardcodate)
|
|
□ Nu duplică CSS din componentele mobile
|
|
```
|
|
|
|
### Backend Development
|
|
- Place logic in **services**, not routers
|
|
- Use `@cached` decorator for ALL database queries
|
|
- Cache schema lookups separately (24h TTL)
|
|
|
|
**Service pattern**:
|
|
```python
|
|
from app.cache.decorators import cached
|
|
|
|
class YourService:
|
|
@staticmethod
|
|
@cached(cache_type='your_data', key_params=['company_id', 'username'])
|
|
async def get_data(company_id: int, username: str):
|
|
# Query Oracle here
|
|
```
|
|
|
|
### Authentication
|
|
- JWT structure: `username`, `user_id`, `companies[]`, `permissions[]`, `exp`, `iat`, `type`
|
|
- Middleware: `shared/auth/middleware.py` (auto-injects `request.state.user`)
|
|
- Rate limiting: 5 req/5 min for `/auth/*`
|
|
|
|
---
|
|
|
|
## Documentation Index
|
|
|
|
| Topic | File | Description |
|
|
|-------|------|-------------|
|
|
| **Setup** | `README.md` | Commands, testing, deployment |
|
|
| **Architecture** | `docs/ARCHITECTURE-DECISIONS.md` | Critical decisions |
|
|
| **CSS Quick Start** | `docs/ONBOARDING_CSS.md` | START HERE for frontend |
|
|
| **CSS Patterns** | `docs/CSS_PATTERNS.md` | Cards, forms, buttons, tables |
|
|
| **Design Tokens** | `docs/DESIGN_TOKENS.md` | Colors, spacing, dark mode |
|
|
| **Mobile Patterns** | `docs/MOBILE_PATTERNS.md` | Mobile components, touch UX |
|
|
| **Data Entry** | `docs/data-entry/DATA-ENTRY-MODULE.md` | SQLModel, workflow |
|
|
| **Telegram** | `docs/telegram/README.md` | Bot development |
|
|
| **Deployment** | `deployment/linux/README.md` | Deploy from LXC |
|
|
| **Troubleshooting** | `docs/troubleshooting/` | Debugging guides, memory leaks |
|
|
|
|
---
|
|
|
|
## Learned Patterns & Known Issues
|
|
|
|
> **Patterns/Gotchas from previous sessions**: Auto-loaded from `.claude/rules/auto-build-memory.md`
|
|
|
|
### Known Issues & Fixes
|
|
|
|
#### Mobile File Upload ERR_NETWORK (Android/iOS)
|
|
**Problem**: File uploads fail with `ERR_NETWORK` (status 0) on mobile browsers.
|
|
|
|
**Cause**: Android/iOS browsers invalidate File object references after accessing properties due to SnapshotState in W3C File API. See [Chromium Bug #40703873](https://issues.chromium.org/40703873).
|
|
|
|
**Solution**: Clone the file into memory immediately after selection:
|
|
```javascript
|
|
const handleFile = async (file) => {
|
|
// FIX: Clone file to memory to avoid SnapshotState invalidation
|
|
const arrayBuffer = await file.arrayBuffer()
|
|
const clonedFile = new File([arrayBuffer], file.name, {
|
|
type: file.type,
|
|
lastModified: file.lastModified
|
|
})
|
|
selectedFile.value = clonedFile
|
|
}
|
|
```
|
|
|
|
**Applied in**: `src/modules/data-entry/components/ocr/OCRUploadZone.vue`
|
|
|
|
---
|
|
|
|
## Security
|
|
|
|
- Never commit `.env` files
|
|
- SSH keys in `ssh-tunnel/secrets/` (gitignored)
|
|
- Rate limiting in auth middleware
|
|
|
|
---
|
|
|
|
## Tech Stack
|
|
|
|
**Backend**: FastAPI, python-oracledb, JWT, Pydantic
|
|
**Frontend**: Vue.js 3, PrimeVue, Pinia, Vite
|
|
**Telegram**: python-telegram-bot, SQLite, httpx
|
|
**Infra**: Oracle DB, SSH Tunnel, IIS (Windows prod)
|