🏗️ Przegląd Architektury¶
Ten dokument opisuje ogólną architekturę systemu Panel Księgowy.
🎯 Architektura wysokiego poziomu¶
Panel Księgowy to multi-tenant SaaS platform zbudowana na Django 5.2, która umożliwia biurom rachunkowym zarządzanie klientami, fakturami, zadaniami i innymi aspektami działalności.
Kluczowe cechy¶
- Multi-tenancy - Każdy zespół (Team) ma izolowaną bazę danych logicznie
- Team-based URLs - Wszystkie URL-e są w kontekście zespołu
- Function-based views - Preferowane nad class-based views
- HTMX + Alpine.js - Nowoczesny frontend bez SPA
- PostgreSQL - Baza danych główna
- Redis - Cache i message broker
- Celery - Asynchroniczne zadania
🏗️ Warstwy architektury¶
1. Frontend Layer¶
Technologie: - HTMX - Interakcje z backendem (AJAX bez JavaScript) - Alpine.js - Interakcje po stronie klienta - Tailwind CSS 4 - Framework CSS - DaisyUI - Komponenty UI - Vite - Build system
Charakterystyka: - Progressive Enhancement - Działa bez JavaScript, lepiej z nim - Server-side rendering - Django templates - No SPA - Tradycyjne request/response z HTMX enhancements
2. Application Layer¶
Technologie: - Django 5.2 - Framework backendowy - Python 3.12 - Język programowania - Django ORM - Warstwa dostępu do danych - Celery - Asynchroniczne zadania - Django REST Framework - API (gdy potrzebne)
Charakterystyka: - Function-based views - Preferowane - Team isolation - Wszystkie zapytania filtrowane po team - BaseTeamModel - Wszystkie modele biznesowe dziedziczą po BaseTeamModel
3. Data Layer¶
Technologie: - PostgreSQL - Baza danych główna - Redis - Cache i message broker dla Celery - File Storage - Przechowywanie plików (local/S3)
Charakterystyka:
- Multi-tenant - Fizycznie jedna baza, logicznie izolowana
- Team filtering - Wszystkie zapytania filtrowane po team_id
- Indexes - Zoptymalizowane indeksy na team_id
🔐 Multi-tenancy¶
Virtual Tenant Isolation¶
System używa virtual tenant isolation - wszystkie dane są w jednej bazie PostgreSQL, ale logicznie izolowane przez filtrowanie po team_id.
Zalety: - ✅ Prostsze zarządzanie (jedna baza) - ✅ Łatwiejsze backup i restore - ✅ Lepsze wykorzystanie zasobów - ✅ Prostsze skalowanie
Bezpieczeństwo:
- ✅ Wszystkie zapytania filtrowane po team_id
- ✅ BaseTeamModel wymusza team field
- ✅ Decorators sprawdzają dostęp do team
- ✅ Brak możliwości cross-team access
Team Model¶
class Team(SubscriptionModelBase, BaseModel):
"""Team (virtual tenant) model."""
name = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
nip = models.CharField(max_length=10)
# ... inne pola
BaseTeamModel¶
class BaseTeamModel(BaseModel):
"""Abstract model for objects that are part of a team."""
team = models.ForeignKey("teams.Team", on_delete=models.CASCADE)
class Meta:
abstract = True
Użycie:
class Client(BaseTeamModel):
name = models.CharField(max_length=200)
nip = models.CharField(max_length=10)
# team field jest automatycznie dodany
🌐 URL Structure¶
Team-based URLs¶
Wszystkie URL-e biznesowe są w kontekście zespołu:
Przykłady:
- /a/my-team/clients/ - Lista klientów
- /a/my-team/clients/123/ - Szczegóły klienta
- /a/my-team/invoicing/ - Faktury
- /a/my-team/tasks/ - Zadania
Decorators¶
@login_and_team_required
def client_list(request, team_slug):
"""Lista klientów - wymaga logowania i członkostwa w team."""
team = request.team # Automatycznie dodane przez decorator
clients = Client.objects.filter(team=team)
# ...
📦 Struktura modułów¶
Każdy moduł ma standardową strukturę:
apps/module_name/
├── __init__.py
├── models/
│ ├── __init__.py
│ └── main.py # BaseTeamModel models
├── views/
│ ├── __init__.py
│ ├── dashboard.py # Dashboard view
│ ├── settings.py # Settings view
│ └── crud.py # CRUD views
├── templates/module_name/
│ ├── dashboard.html
│ └── settings.html
├── urls.py # team_urlpatterns
├── admin.py
├── forms.py
├── services.py # Business logic
├── tasks.py # Celery tasks
└── README.md
🔄 Request Flow¶
Standardowy request¶
- User → Kliknięcie linku/przycisku
- HTMX → AJAX request do Django
- Django → Decorator sprawdza dostęp do team
- View → Pobiera dane (filtrowane po team)
- Template → Renderuje HTML
- HTMX → Wstawia HTML do DOM
Przykład¶
# views.py
@login_and_team_required
def client_list(request, team_slug):
clients = Client.objects.filter(team=request.team)
return render(request, 'crm/client_list.html', {
'clients': clients
})
<!-- client_list.html -->
{% for client in clients %}
<div hx-get="/a/{{ team.slug }}/clients/{{ client.id }}/"
hx-target="#client-detail">
{{ client.name }}
</div>
{% endfor %}
🗄️ Database Schema¶
Kluczowe tabele¶
- teams_team - Zespoły (virtual tenants)
- teams_membership - Członkostwo użytkowników w zespołach
- crm_client - Klienci (z
team_id) - invoicing_invoice - Faktury (z
team_id) - tasks_task - Zadania (z
team_id)
Relacje¶
🔧 Services Layer¶
Business Logic¶
Business logic jest w services.py:
# services.py
class ClientService:
@staticmethod
def create_client(team, data):
"""Tworzy klienta z walidacją."""
# Walidacja
# Tworzenie
# Integracje
return client
📚 Więcej informacji¶
- Multi-tenancy - Szczegółowa architektura wielodostępowa
- Bazy Danych - Struktura bazy danych
- API - Architektura API
Ostatnia aktualizacja: 2025-11-29
Wersja dokumentacji: 1.0