Files
prov/CLAUDE.md
T
kerimatilganandClaude Opus 4.7 55ec916f35 Initial commit: Provisions-Tracker application
Node.js/Express + SQLite + Vanilla JS app for managing employee
commissions on telecom activations (Telekom, Vodafone, O2, 1&1).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 21:07:05 +02:00

225 lines
9.6 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a **Provisions-Tracker** (Commission Tracker) application for managing employee commissions on telecommunications activations ("Schaltungen"). Built as a Node.js/Express backend with SQLite database and vanilla JavaScript frontend.
**Purpose**: Track commissions for telecom providers (Telekom, Vodafone, O2, 1&1), including tariffs, customer data, documents, and complex commission calculations.
## Development Commands
### Running the Application
```bash
# Production mode
npm start
# Development mode with auto-restart
npm run dev
# Install dependencies
npm install
```
The application runs on `http://localhost:3000` by default (configurable via `PORT` environment variable).
### Database
- SQLite database file: `provision.db` (auto-created on first run)
- Database initialization happens automatically via `initDatabase()` in [database.js](database.js)
- Backup file exists: `provision.db.backup`
- No migrations system - uses `CREATE TABLE IF NOT EXISTS` and `ALTER TABLE` with error handling
## Architecture Overview
### Three-Tier Structure
**Backend** ([server.js](server.js) - ~1987 lines)
- Express.js REST API with ~40+ endpoints
- Handles business logic, commission calculations, and database operations
- File upload handling via Multer (10MB limit)
- CORS enabled for development
**Database** ([database.js](database.js) - 288 lines)
- SQLite with 12+ tables
- Key tables: `anbieter` (providers), `tarife` (tariffs), `schaltungen` (connections/commissions), `dokumente` (documents)
- Complex commission system with multiple rule types (fixed/percentage)
- Includes soft-delete tracking (`geloeschte_schaltungen`)
**Frontend** ([public/](public/))
- Single-page app: [index.html](public/index.html), [script.js](public/script.js) (~4000+ lines)
- Tab-based navigation (Erfassung, Übersicht, Provisionen, Admin, Gelöschte)
- Preloading strategy for fast tab switching
- Drag-and-drop file uploads
### Key Database Tables and Relationships
```
anbieter (providers)
├─→ tarife (tariffs) - provision_euro, mitarbeiter_provision
│ ├─→ provisionsregeln (tariff-specific commission rules)
│ └─→ tarifoptionen_tarife (M2M link to options)
├─→ anbieter_provisionsregeln (global provider commission rules)
└─→ mitarbeiter_prozentsaetze (employee percentage rates per provider)
schaltungen (main commissions table)
├─→ anbieter_id, tarif_id (foreign keys)
├─→ dokumente (uploaded documents)
├─→ schaltungen_tarifoptionen (M2M selected tariff options)
└─→ hardware_ek, kundenverkaufspreis_netto (hardware pricing)
tarifoptionen_new (tariff options - new structure)
└─→ tarifoptionen_tarife (M2M relationship to tarifs)
tarifoptionen (old structure - kept for migration compatibility)
```
### Commission Calculation System
The app supports multiple commission calculation methods with complex fallback logic:
1. **Tariff-specific rules** (`provisionsregeln` table)
- Fixed amount or percentage
- Employee commission (verkaeufer_provision)
2. **Global provider rules** (`anbieter_provisionsregeln` table)
- Applied when no tariff-specific rule exists
3. **Direct tariff amounts** (fallback)
- `tarife.provision_euro` - company commission
- `tarife.mitarbeiter_provision` - employee commission
4. **Tariff options** (`tarifoptionen`)
- Additional commission adjustments per activation
- Can be positive or negative (e.g., rebates)
- Many-to-many relationship (options can apply to multiple tariffs)
**API endpoint**: `GET /api/schaltungen/:id/provision` - calculates total commission for a specific activation.
### Migration Notes
The system includes an in-place migration from old tarifoptionen structure (one-to-many with tarifs) to new structure (many-to-many via `tarifoptionen_new` and `tarifoptionen_tarife`). Migration runs automatically on startup via `migrateToNewTarifoptionen()` in [database.js:228-266](database.js#L228-L266).
## API Endpoint Categories
### Anbieter (Providers)
- `GET /api/anbieter` - List all providers
- `POST /api/anbieter` - Add provider
- `DELETE /api/anbieter/:id` - Delete provider (with dependency checks)
- `GET /api/anbieter/:id/provisionsregeln` - Get global commission rules
- `POST /api/anbieter-provisionsregeln` - Add global rule
- `PUT /api/anbieter-provisionsregeln/:id` - Update global rule
### Tarife (Tariffs)
- `GET /api/tarife` - List all tariffs
- `GET /api/tarife/:anbieter_id` - List tariffs for provider
- `GET /api/tarif/:id` - Get single tariff
- `POST /api/tarife` - Add tariff
- `PUT /api/tarife/:id` - Update tariff
- `DELETE /api/tarife/:id` - Delete tariff (with dependency checks)
- `GET /api/tarife/:id/provisionsregeln` - Get tariff commission rules
- `POST /api/provisionsregeln` - Add tariff rule
- `PUT /api/provisionsregeln/:id` - Update tariff rule
- `PUT /api/tarife/:id/mitarbeiter-provision` - Update employee commission
### Schaltungen (Commissions/Activations)
- `GET /api/schaltungen` - List all activations
- `POST /api/schaltungen` - Create activation
- `PUT /api/schaltungen/:id` - Update activation
- `DELETE /api/schaltungen/:id` - Delete activation (soft delete with reason tracking)
- `GET /api/schaltungen/:id/provision` - Calculate commission for activation
- `GET /api/provisionen` - Get commission overview/report
- `GET /api/geloeschte-schaltungen` - List deleted activations
### Dokumente (Documents)
- `POST /api/schaltungen/:id/dokumente` - Upload document (multipart/form-data)
- `GET /api/schaltungen/:id/dokumente` - List documents for activation
- `GET /api/dokumente/:id/download` - Download document
- `DELETE /api/dokumente/:id` - Delete document (removes file from disk)
### Tarifoptionen (Tariff Options)
- `GET /api/tarifoptionen` - List all options (old structure)
- `GET /api/tarifoptionen/multi` - List all options (new structure)
- `POST /api/tarifoptionen/multi` - Add option (new structure)
- `PUT /api/tarifoptionen/multi/:id` - Update option (new structure)
- `DELETE /api/tarifoptionen/multi/:id` - Delete option (new structure)
- `GET /api/schaltungen/:id/tarifoptionen` - Get options for activation
- `POST /api/schaltungen/:id/tarifoptionen` - Link option to activation
- `DELETE /api/schaltungen/:schaltung_id/tarifoptionen/:tarifoption_id` - Unlink option
### Mitarbeiter (Employee Settings)
- `GET /api/anbieter/:id/mitarbeiter-prozentsaetze` - Get employee percentages for provider
- `POST /api/mitarbeiter-prozentsaetze` - Add percentage rate
- `DELETE /api/mitarbeiter-prozentsaetze/:id` - Delete percentage rate
## Important Implementation Details
### File Uploads
- Storage: `uploads/` directory (created automatically)
- Naming: `{timestamp}-{random}.{extension}`
- Limit: 10MB per file
- Supported types: PDF, JPG, JPEG, PNG, DOC, DOCX (enforced client-side)
- Files are physically deleted when document is removed
### Frontend State Management
- **Preloading**: App preloads all tab data in background after 1 second delay for faster navigation
- **Tab switching**: Uses cached data when available (`showTab()` checks if data exists)
- Global variables: `currentSchaltungId`, `uploadedFiles`
- Message system: Toast notifications via `showMessage()` overlay
### Database Connection Pattern
**Singleton Pattern** - A single persistent database connection is used throughout the application lifecycle:
```javascript
const db = getDatabase(); // Returns singleton instance
// ... do work ...
// NO db.close() - connection persists
```
- Connection is opened once on startup and reused
- Foreign keys are enabled after initialization (`PRAGMA foreign_keys = ON`)
- Busy timeout set to 3000ms for concurrent access handling
- Graceful shutdown closes connection on SIGINT/SIGTERM
### Delete Operations
- **Soft delete**: Schaltungen are moved to `geloeschte_schaltungen` table with reason and timestamp
- **CASCADE delete**: Deleting a Schaltung automatically removes:
- Associated documents from database (via `ON DELETE CASCADE`)
- Document files from filesystem (handled in endpoint)
- Linked tarifoptionen (via `ON DELETE CASCADE`)
- **Hard delete**: Individual documents physically removed from filesystem when deleted
- **Dependency checks**: Providers and Tariffs check for usage before deletion
### Language
- **UI/Database**: German (Anbieter, Tarife, Schaltungen, etc.)
- **Code**: Mixed German/English
- **Comments**: Mostly English in code, German in UI strings
## Testing Data
Default data seeded on first run:
- **Providers**: Telekom, Vodafone, O2, 1&1
- **Tariffs**: 10 example tariffs with commission amounts
- **Employee percentages**: 8-10% per provider
- **Tariff options**: 5 example options including rebates
- **Global rules**: Example O2 (fixed 20€) and 1&1 (12% percentage) rules
## Common Development Patterns
### Adding a New API Endpoint
1. Add route in [server.js](server.js) following existing patterns
2. Use `getDatabase()` to open connection
3. Always call `db.close()` in callbacks
4. Return JSON with proper error handling
5. Update frontend in [script.js](script.js) with corresponding API call
### Adding a Database Table
1. Add `CREATE TABLE IF NOT EXISTS` in [database.js](database.js) `initDatabase()`
2. Add within `db.serialize()` block
3. Consider foreign key constraints
4. Add seed data with `INSERT OR IGNORE` if needed
### Modifying Commission Logic
- Main calculation logic is in `GET /api/schaltungen/:id/provision`
- Fallback order: provisionsregeln → anbieter_provisionsregeln → direct tariff amounts
- Always recalculate when tariff/provider/options change
- Employee commission calculated separately from company commission