time-tracker/docu/code_examples/gorm_entities.go

105 lines
2.8 KiB
Go

package entities
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
// BaseEntity enthält gemeinsame Felder für alle Entitäten
type BaseEntity struct {
ID uuid.UUID `gorm:"type:uuid;primary_key"`
CreatedAt time.Time `gorm:"autoCreateTime"`
UpdatedAt time.Time `gorm:"autoUpdateTime"`
DeletedAt gorm.DeletedAt `gorm:"index"`
}
// BeforeCreate setzt eine neue UUID vor dem Erstellen
func (base *BaseEntity) BeforeCreate(tx *gorm.DB) error {
if base.ID == uuid.Nil {
base.ID = uuid.New()
}
return nil
}
// TenantEntity erweitert BaseEntity um Company-ID für Multi-Tenancy
type TenantEntity struct {
BaseEntity
CompanyID uuid.UUID `gorm:"type:uuid;index:idx_tenant"`
}
// Role repräsentiert eine Benutzerrolle
type Role struct {
BaseEntity
Name string `gorm:"unique;not null"`
Description string
Permissions []Permission `gorm:"many2many:role_permissions;"`
}
// Permission repräsentiert eine einzelne Berechtigung
type Permission struct {
BaseEntity
Resource string `gorm:"not null"`
Action string `gorm:"not null"`
UniqueID string `gorm:"uniqueIndex"`
}
// User repräsentiert einen Benutzer im System
type User struct {
TenantEntity
Email string `gorm:"uniqueIndex;not null"`
FirstName string
LastName string
PasswordHash string `gorm:"not null"`
RoleID uuid.UUID `gorm:"type:uuid"`
Role Role `gorm:"foreignKey:RoleID"`
HourlyRate float64
IsActive bool `gorm:"default:true"`
}
// FullName gibt den vollständigen Namen des Benutzers zurück
func (u User) FullName() string {
return u.FirstName + " " + u.LastName
}
// TimeEntry repräsentiert eine Zeitbuchung
type TimeEntry struct {
TenantEntity
UserID uuid.UUID `gorm:"type:uuid;index:idx_user"`
User User `gorm:"foreignKey:UserID"`
ProjectID uuid.UUID `gorm:"type:uuid;index:idx_project"`
Project Project `gorm:"foreignKey:ProjectID"`
ActivityID uuid.UUID `gorm:"type:uuid"`
Activity Activity `gorm:"foreignKey:ActivityID"`
TaskID *uuid.UUID `gorm:"type:uuid;null"`
Task *Task `gorm:"foreignKey:TaskID"`
StartTime time.Time `gorm:"not null;index:idx_time_range"`
EndTime time.Time `gorm:"not null;index:idx_time_range"`
DurationMinutes int `gorm:"not null"`
Description string
BillablePercentage int `gorm:"default:100"`
BillingRate float64
}
type Project struct {
TenantEntity
Name string
}
type Activity struct {
TenantEntity
Name string
}
type Task struct {
TenantEntity
Name string
}
// CalculateBillableAmount berechnet den abrechenbaren Betrag
func (t TimeEntry) CalculateBillableAmount() float64 {
hours := float64(t.DurationMinutes) / 60.0
return hours * t.BillingRate * (float64(t.BillablePercentage) / 100.0)
}