274 lines
15 KiB
Markdown
274 lines
15 KiB
Markdown
|
|
# Architecture – Rentman.io Clone
|
|||
|
|
|
|||
|
|
> **Version:** 1.0
|
|||
|
|
> **Date:** 2026-05-31
|
|||
|
|
> **Project:** Rentman.io-Nachbau
|
|||
|
|
> **Architect:** Solution Architect (A0 Software Orchestrator)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Table of Contents
|
|||
|
|
|
|||
|
|
1. [Tech-Stack](#tech-stack)
|
|||
|
|
2. [System Components](#system-components)
|
|||
|
|
3. [API Design](#api-design)
|
|||
|
|
4. [Authentication & Authorization](#authentication--authorization)
|
|||
|
|
5. [Multi-Tenant Strategy](#multi-tenant-strategy)
|
|||
|
|
6. [Deployment Approach](#deployment-approach)
|
|||
|
|
7. [Module Boundaries & Data Flow](#module-boundaries--data-flow)
|
|||
|
|
8. [Risk Notes](#risk-notes)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Tech-Stack
|
|||
|
|
|
|||
|
|
### Backend
|
|||
|
|
- **Language:** Python 3.12+
|
|||
|
|
- **Framework:** FastAPI 0.115+ (async, high-performance, auto-docs)
|
|||
|
|
- **ORM:** SQLAlchemy 2.0 with Alembic for migrations
|
|||
|
|
- **Database:** SQLite for local development → PostgreSQL 16 for production
|
|||
|
|
- **Caching:** Redis for session storage, rate limiting, and cache layer
|
|||
|
|
- **Background Tasks:** Celery with Redis broker for async jobs (PDF generation, email)
|
|||
|
|
- **File Storage:** Local filesystem for dev; S3-compatible (MinIO/AWS S3) for production
|
|||
|
|
|
|||
|
|
### Frontend
|
|||
|
|
- **Language:** TypeScript 5.x (strict mode)
|
|||
|
|
- **Framework:** React 19 with React Router 7 (routing), TanStack Router also considered
|
|||
|
|
- **State Management:** Zustand (global), React Query (server state)
|
|||
|
|
- **UI Library:** Tailwind CSS 4 + Radix UI (accessible headless components)
|
|||
|
|
- **Build Tool:** Vite 6
|
|||
|
|
- **Testing:** Vitest + React Testing Library
|
|||
|
|
- **Mobile (PWA):** Service Worker with Workbox, Capacitor (for native camera/barcode)
|
|||
|
|
|
|||
|
|
### Mobile App (PWA)
|
|||
|
|
- Progressive Web App with offline support (Service Workers)
|
|||
|
|
- Barcode scanning via Capacitor's Barcode Scanner plugin
|
|||
|
|
- IndexedDB for local data store; sync with backend via REST API
|
|||
|
|
|
|||
|
|
### DevOps & Deployment
|
|||
|
|
- **Containerization:** Docker & Docker Compose
|
|||
|
|
- **CI/CD:** GitHub Actions (build, test, lint, migrate, deploy)
|
|||
|
|
- **Environment:** Local dev with Docker Compose; production on Coolify (CapRover alternative)
|
|||
|
|
- **Monitoring:** Prometheus + Grafana (optional), Sentry for error tracking
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## System Components
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────────────────────────────────┐
|
|||
|
|
│ Rentman-Clone System │
|
|||
|
|
│ │
|
|||
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|||
|
|
│ │ React SPA │ │ PWA Mobile │ │ External APIs│ │ Admin CLI │ │
|
|||
|
|
│ │ (Browser) │ │ (Capacitor) │ │ (Webhooks) │ │ (optional) │ │
|
|||
|
|
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
|
|||
|
|
│ │ │ │ │ │
|
|||
|
|
│ └────────────────┴────────┬────────┴─────────────────┘ │
|
|||
|
|
│ │ │
|
|||
|
|
│ ┌────────▼────────┐ │
|
|||
|
|
│ │ Nginx Reverse │ │
|
|||
|
|
│ │ Proxy (TLS) │ │
|
|||
|
|
│ └────────┬────────┘ │
|
|||
|
|
│ │ │
|
|||
|
|
│ ┌────────▼────────┐ │
|
|||
|
|
│ │ FastAPI App │ │
|
|||
|
|
│ │ (Backend API) │ │
|
|||
|
|
│ │ Port 8000 │ │
|
|||
|
|
│ └───┬───────┬───────┘ │
|
|||
|
|
│ │ │ │
|
|||
|
|
│ ┌────────────▼──┐ ┌──▼────────────┐ │
|
|||
|
|
│ │ Celery Worker │ │ PostgreSQL │ │
|
|||
|
|
│ │ (Background) │ │ / SQLite │ │
|
|||
|
|
│ │ + Redis Queue │ │ │ │
|
|||
|
|
│ └───────┬────────┘ └───────────────┘ │
|
|||
|
|
│ │ │
|
|||
|
|
│ ┌──────────▼──────────┐ │
|
|||
|
|
│ │ Object Storage │ │
|
|||
|
|
│ │ (MinIO / S3) │ │
|
|||
|
|
│ └─────────────────────┘ │
|
|||
|
|
└─────────────────────────────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Component Descriptions
|
|||
|
|
- **React SPA:** Client-side rendered app, communicates via JSON REST API, handles UI rendering. Built with Vite for fast builds.
|
|||
|
|
- **PWA Mobile App:** Same React codebase but served with Service Worker for offline capability; uses Capacitor for camera/barcode scanning. Can be deployed as TWA (Trusted Web Activity) on Android or via iOS WebAPKs.
|
|||
|
|
- **External APIs (Webhooks):** Endpoints for third-party integrations (calendars, external CRM/ERP). Can also consume webhooks.
|
|||
|
|
- **Nginx Reverse Proxy:** SSL termination, static file serving (for SPA), rate limiting, and optional load balancing.
|
|||
|
|
- **FastAPI Backend:** RESTful API with JWT auth, RBAC, openapi schema. Implements all business logic. Uses SQLAlchemy async sessions.
|
|||
|
|
- **Celery Worker:** Offloads long-running tasks: PDF generation, mass exports, email sending, webhook dispatching. Uses Redis as message broker.
|
|||
|
|
- **Redis:** Used for Celery broker, also for caching query results (Redis Cache), session storage, and rate limiting counters.
|
|||
|
|
- **PostgreSQL / SQLite:** SQLite for local dev (single file), PostgreSQL for production. Both accessed through same SQLAlchemy models, migrations applied via Alembic.
|
|||
|
|
- **Object Storage (MinIO/S3):** Stores uploaded documents, equipment images, generated PDFs/CSVs. Provides signed URLs for download.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## API Design
|
|||
|
|
|
|||
|
|
### General Principles
|
|||
|
|
- RESTful JSON API.
|
|||
|
|
- Base URL: `/api/v1/` (versioned for future updates).
|
|||
|
|
- Authentication: Bearer JWT token in `Authorization` header.
|
|||
|
|
- Standard HTTP status codes: 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable, 500 Internal Server Error.
|
|||
|
|
- Pagination: all list endpoints return JSON with `items`, `total`, `page`, `size`.
|
|||
|
|
- Filtering: query parameters `?status=X&project_type=Y&sort=created_at&order=asc`.
|
|||
|
|
- Nested resources for sub-entities (e.g., `/projects/{project_id}/subprojects`).
|
|||
|
|
- OpenAPI (Swagger) auto-generated at `/docs` and `/redoc`.
|
|||
|
|
|
|||
|
|
### Endpoint Overview
|
|||
|
|
|
|||
|
|
**Auth:**
|
|||
|
|
- `POST /api/v1/auth/login` – login (email, password) → JWT token + refresh token
|
|||
|
|
- `POST /api/v1/auth/refresh` – refresh token
|
|||
|
|
- `POST /api/v1/auth/register` – self-service registration (tenant creation)
|
|||
|
|
|
|||
|
|
**Users & Roles:**
|
|||
|
|
- `GET/POST /api/v1/users` – list/create users (admin)
|
|||
|
|
- `GET/PUT/DELETE /api/v1/users/{id}` – user CRUD
|
|||
|
|
- `GET/PUT /api/v1/roles` – roles management
|
|||
|
|
|
|||
|
|
**Projects:**
|
|||
|
|
- `GET/POST /api/v1/projects` – list/create
|
|||
|
|
- `GET/PUT/DELETE /api/v1/projects/{id}` – project CRUD
|
|||
|
|
- `GET /api/v1/projects/{id}/subprojects` – subprojects
|
|||
|
|
- `POST /api/v1/projects/{id}/subprojects` – create subproject
|
|||
|
|
- `GET/PUT/DELETE /api/v1/projects/{project_id}/subprojects/{id}` – subproject CRUD
|
|||
|
|
- Project function groups: `/projects/{project_id}/functiongroups` (nested)
|
|||
|
|
- Project functions: `/projects/{project_id}/functiongroups/{group_id}/functions`
|
|||
|
|
- Equipment groups: `/projects/{project_id}/equipmentgroups`
|
|||
|
|
- Equipment items within group: `/projects/{project_id}/equipmentgroups/{group_id}/equipment`
|
|||
|
|
- Crew assignments: `/projects/{project_id}/crew` (via functions)
|
|||
|
|
- Vehicle assignments: `/projects/{project_id}/vehicles`
|
|||
|
|
- Quotes: `/projects/{project_id}/quotes`
|
|||
|
|
- Invoices: `/projects/{project_id}/invoices`
|
|||
|
|
|
|||
|
|
**Equipment Catalog:**
|
|||
|
|
- `GET/POST /api/v1/equipment` – list/create
|
|||
|
|
- `GET/PUT/DELETE /api/v1/equipment/{id}` – CRUD
|
|||
|
|
- `GET /api/v1/equipment/{id}/availability` – availability timeline
|
|||
|
|
|
|||
|
|
**Crew Catalog:**
|
|||
|
|
- `GET/POST /api/v1/crew` – list/create
|
|||
|
|
- `GET/PUT/DELETE /api/v1/crew/{id}` – CRUD
|
|||
|
|
- `GET /api/v1/crew/{id}/availability` – availability
|
|||
|
|
|
|||
|
|
**Vehicles:**
|
|||
|
|
- `GET/POST /api/v1/vehicles` – list/create
|
|||
|
|
- `GET/PUT/DELETE /api/v1/vehicles/{id}` – CRUD
|
|||
|
|
|
|||
|
|
**Contacts:**
|
|||
|
|
- `GET/POST /api/v1/contacts` – list/create
|
|||
|
|
- `GET/PUT/DELETE /api/v1/contacts/{id}` – CRUD
|
|||
|
|
|
|||
|
|
**Project Requests:**
|
|||
|
|
- `GET/POST /api/v1/requests` – public/private
|
|||
|
|
- `GET/PUT /api/v1/requests/{id}` – read/update
|
|||
|
|
- `POST /api/v1/requests/{id}/convert` – convert to project
|
|||
|
|
|
|||
|
|
**Documents:**
|
|||
|
|
- `GET/POST /api/v1/documents` – list/upload
|
|||
|
|
- `GET/DELETE /api/v1/documents/{id}` – download/delete
|
|||
|
|
- Templates: `/api/v1/templates` (admin)
|
|||
|
|
|
|||
|
|
**Reports:**
|
|||
|
|
- `GET /api/v1/reports/finance` – financial KPIs
|
|||
|
|
- `GET /api/v1/reports/equipment-utilization` – equipment utilization
|
|||
|
|
- `GET /api/v1/reports/project-stats` – project statistics
|
|||
|
|
|
|||
|
|
**Export:**
|
|||
|
|
- `POST /api/v1/export/{module}` – asynchronous export to CSV/Excel
|
|||
|
|
|
|||
|
|
**Webhooks:**
|
|||
|
|
- `GET/POST /api/v1/webhooks` – manage webhook subscriptions
|
|||
|
|
- `POST /api/v1/webhooks/{id}/trigger` – test trigger
|
|||
|
|
|
|||
|
|
**Admin:**
|
|||
|
|
- `GET /api/v1/audit-log` – audit log entries
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Authentication & Authorization
|
|||
|
|
|
|||
|
|
### Authentication
|
|||
|
|
- JWT access tokens (short-lived, 30 minutes) + refresh tokens (24 hours, stored in httpOnly cookie or secure storage).
|
|||
|
|
- Password hashing with bcrypt.
|
|||
|
|
- Optional OAuth2/OpenID Connect in V2 (not MVP).
|
|||
|
|
- Self-service registration creates a new tenant account (company) and admin user.
|
|||
|
|
|
|||
|
|
### Authorization – RBAC
|
|||
|
|
- Role-based access control with four fixed roles: Admin, Project Manager, Warehouse Operator, Freelancer.
|
|||
|
|
- Custom roles can be defined later; permissions are defined as granular rights:
|
|||
|
|
- Module-level: `projects:read`, `projects:write`, `projects:delete`, `equipment:read`, etc.
|
|||
|
|
- Object-level: user can only access projects they are assigned to (or all for admin).
|
|||
|
|
- Roles are stored as list of permissions in `Role` model.
|
|||
|
|
- Middleware checks token claims and resolves permissions; `Depends()` function in FastAPI routes.
|
|||
|
|
|
|||
|
|
### Multi-Tenant Strategy
|
|||
|
|
- **Shared Database with Tenant ID:** Each table contains a `tenant_id` (UUID) foreign key to `Account` table.
|
|||
|
|
- Row-Level Security: SQLAlchemy queries automatically filter by the tenant associated with the authenticated user's `account_id` (from JWT).
|
|||
|
|
- Isolation: one account cannot see another's data.
|
|||
|
|
- Onboarding: registration creates a new `Account` and an initial admin user.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Deployment Approach
|
|||
|
|
|
|||
|
|
### Local Development
|
|||
|
|
- Docker Compose with services: backend (FastAPI hot-reload), frontend (Vite dev server), PostgreSQL, Redis, MinIO.
|
|||
|
|
- SQLite as default for quick dev (just set `DATABASE_URL=sqlite:///./rentman.db`), but Docker-Compose uses PostgreSQL.
|
|||
|
|
- No volumes; data in container.
|
|||
|
|
|
|||
|
|
### Production (Coolify)
|
|||
|
|
- Docker Compose as deployable artifact.
|
|||
|
|
- Coolify handles SSL, domain routing, environment variables.
|
|||
|
|
- CI/CD: GitHub Actions build test, then push image to registry; Coolify webhook triggers redeploy.
|
|||
|
|
- Database backups via Coolify's built-in PostgreSQL backup feature.
|
|||
|
|
- File storage: S3 bucket (MinIO or AWS S3).
|
|||
|
|
|
|||
|
|
### Scalability
|
|||
|
|
- Backend stateless → horizontal scaling with multiple API instances behind load balancer.
|
|||
|
|
- Celery workers can be scaled independently.
|
|||
|
|
- PostgreSQL read replicas for heavy reporting.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Module Boundaries & Data Flow
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
React SPA <──> FastAPI <──> SQLAlchemy <──> Database
|
|||
|
|
<──> Celery (Redis) <──> Email/PDF/S3
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Modules (in backend):**
|
|||
|
|
- `auth` – login, register, refresh
|
|||
|
|
- `users` – user management, roles
|
|||
|
|
- `projects` – project CRUD, subprojects, function groups, functions
|
|||
|
|
- `equipment` – equipment catalog, categories, stock locations
|
|||
|
|
- `crew` – crew catalog, availability
|
|||
|
|
- `vehicles` – vehicles, assignments
|
|||
|
|
- `contacts` – contacts (companies/persons)
|
|||
|
|
- `project_requests` – public request handling
|
|||
|
|
- `quotes_invoices` – quotes, invoices, templates, PDF generation
|
|||
|
|
- `documents` – file uploads, downloads
|
|||
|
|
- `reports` – analytics endpoints
|
|||
|
|
- `webhooks` – manage subscriptions, dispatch
|
|||
|
|
|
|||
|
|
**Frontend (React):**
|
|||
|
|
- `pages/` – top-level routes
|
|||
|
|
- `components/` – reusable UI (forms, tables, modals)
|
|||
|
|
- `hooks/` – custom hooks for API calls
|
|||
|
|
- `stores/` – Zustand stores (global state)
|
|||
|
|
- `services/` – API client (axios/fetch wrappers)
|
|||
|
|
- `i18n/` – translations (DE, EN)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Risk Notes
|
|||
|
|
- **SQLite vs PostgreSQL discrepancies:** SQLite doesn't support some SQL features (e.g., `ALTER COLUMN`). Use Alembic to handle dialect differences; tests must run on PostgreSQL.
|
|||
|
|
- **Offline Sync Conflicts:** Offline-first with Last-Write-Wins may cause data loss if two users edit same entity offline. For MVP, limited to equipment status and packlist checkmarks; acceptable.
|
|||
|
|
- **Performance with large rental sets:** 500k equipment items → need indexing on tenant_id, status, and category. Reporting queries may be slow; consider materialized views.
|
|||
|
|
- **Security:** JWT secret must be managed; never hardcoded. Use environment variable. Rate limiting prevents brute-force attacks.
|
|||
|
|
- **Multi-Tenant Data Isolation:** Must ensure all queries include tenant filter. Implement a SQLAlchemy query filter on session creation to avoid accidental leaks.
|
|||
|
|
- **PWA Barcode Scanning:** Capacitor camera plugin may require additional permissions; need to handle permission prompts gracefully.
|
|||
|
|
- **Complexity of Project Hierarchy:** Project → Subproject → FunctionGroup → Function → (Crew/Equipment) is deep; ensure API design is consistent and documentation clear.
|