95b581e8c5
fix(automation): implement all 6 actions + real cron parser fix(db): pq.Array for TEXT[], add sqlmock tests fix(schema): single source migrations docs: v2 architecture + frontend refactor proposals
5.7 KiB
5.7 KiB
BOC v2 — Architecture Proposal
Nuvarande Problem (v1.0)
- 13K rader Go i ett enda monolit-paket
- 20 handlers i samma package, delar
*sql.DB - Ingen repository pattern — SQL direkt i handlers
- Ingen service layer — affärslogik i HTTP-handlers
- Ledger-integration är en pass-through proxy
- Ingen event sourcing trots Kafka-definitioner
- Frontend: 12 HTML-filer med copy-paste
V2 Vision: Clean Architecture
┌─────────────────────────────────────────┐
│ Transport (HTTP / WebSocket / CLI) │
│ - handlers/ chi routers │
│ - middleware/ auth, cors, rate │
│ - dto/ request/response │
├─────────────────────────────────────────┤
│ Application (Use Cases) │
│ - services/ business logic │
│ - commands/ CQRS write │
│ - queries/ CQRS read │
├─────────────────────────────────────────┤
│ Domain (Core Business) │
│ - models/ entities, value obj │
│ - events/ domain events │
│ - repositories/ interfaces │
├─────────────────────────────────────────┤
│ Infrastructure │
│ - db/ PostgreSQL impl │
│ - cache/ Redis impl │
│ - events/ Kafka impl │
│ - email/ Resend impl │
│ - pdf/ gofpdf impl │
│ - ledger/ aamos-ledger client │
└─────────────────────────────────────────┘
V2 Förändringar
1. Repository Pattern
// domain/repositories/customer.go
type CustomerRepository interface {
FindByID(ctx context.Context, id uuid.UUID) (*models.Customer, error)
FindByTenant(ctx context.Context, tenantID uuid.UUID, opts ListOptions) ([]*models.Customer, error)
Create(ctx context.Context, c *models.Customer) error
Update(ctx context.Context, c *models.Customer) error
Delete(ctx context.Context, id uuid.UUID) error
}
// infrastructure/db/customer_repo.go
type PostgresCustomerRepo struct { db *sql.DB }
2. Service Layer (Transactions)
// application/services/quote_service.go
func (s *QuoteService) ConvertToOrder(ctx context.Context, quoteID uuid.UUID) (*models.Order, error) {
return s.db.WithTx(ctx, func(tx *sql.Tx) error {
quote, err := s.quotes.FindByIDTx(ctx, tx, quoteID)
if err != nil { return err }
order := quote.ToOrder()
if err := s.orders.CreateTx(ctx, tx, order); err != nil {
return err
}
quote.Status = models.QuoteConverted
return s.quotes.UpdateTx(ctx, tx, quote)
})
}
3. Domain Events (Kafka aktiverad)
// domain/events/customer_events.go
type CustomerCreated struct {
CustomerID uuid.UUID
TenantID uuid.UUID
Email string
}
// application/event_publisher.go
func (p *KafkaPublisher) Publish(ctx context.Context, event domain.Event) error {
// Actually uses Kafka now, not just defined
}
4. Ledger Integration med Circuit Breaker
// infrastructure/ledger/client.go
type LedgerClient struct {
baseURL string
httpClient *http.Client
circuitBreaker *gobreaker.CircuitBreaker
cache cache.Cache
}
func (c *LedgerClient) GetBalanceSheet(ctx context.Context) (*BalanceSheet, error) {
// Cache-first, circuit breaker, fallback to stale data
}
5. CQRS för Analytics
// application/queries/dashboard_query.go
type DashboardQuery struct {
readDB *sql.DB // Read replica or materialized view
}
func (q *DashboardQuery) GetKPIs(ctx context.Context, tenantID uuid.UUID) (*KPIs, error) {
// Optimized read query, no business logic
}
V2 Teknisk Stack
| Komponent | Nu | V2 |
|---|---|---|
| Router | chi | chi (behåll) |
| DB | database/sql | sqlx eller pgx |
| Migrations | custom | golang-migrate |
| Validation | manual | go-playground/validator |
| Testing | testify | testify + sqlmock + dockertest |
| Events | Kafka stub | Kafka aktiverad |
| Cache | Redis wrapper | Redis + cache-aside pattern |
| Frontend | 12 HTML | Vanilla JS SPA (se FRONTEND_REFACTOR_PROPOSAL.md) |
V2 Migreringsplan
Fas 1: Foundation (1 vecka)
- Refactor till Clean Architecture packages
- Implementera Repository pattern för CRM + Sales
- Lägg till service layer med transaktioner
- Riktiga integrationstester med dockertest
Fas 2: Events + Cache (1 vecka)
- Aktivera Kafka publishing från services
- Implementera cache-aside för analytics
- Circuit breaker för ledger
Fas 3: Frontend (3 dagar)
- Vanilla JS SPA shell
- Konvertera moduler en i taget
- Ta bort gamla HTML-filer
Fas 4: Polish (2 dagar)
- OpenAPI/Swagger docs
- Health checks för alla dependencies
- Metrics (Prometheus)
- Structured logging med trace IDs
V2 "Inte Nu"
- GraphQL (YAGNI)
- Microservices (för tidigt)
- Kubernetes operators (overkill)
- React/Vue (för tungt)
Sammanfattning
V2 handlar inte om nya features. V2 handlar om att det vi har faktiskt fungerar pålitligt.
Nuvarande v1.0 är en demo som ser komplett ut men har:
- Säkerhetshål (fixade idag)
- Tysta databasfel (fixade idag)
- Ingen transaktionssäkerhet
- Död kod (Rust, C, Kafka)
- Noll testtäckning
V2 = produktionsklar.