149 lines
4.4 KiB
Go
149 lines
4.4 KiB
Go
package model
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Project represents a project in the system
|
|
type Project struct {
|
|
BaseModel
|
|
Name string `json:"name" gorm:"not null;type:varchar(255)"`
|
|
Description string `json:"description" gorm:"type:text"`
|
|
OwnerID string `json:"owner_id" gorm:"not null;type:uuid;index;references:users(id)"`
|
|
TypeID string `json:"type_id" gorm:"not null;type:uuid;index;references:types(id)"`
|
|
Owner User `json:"owner,omitempty" gorm:"foreignKey:OwnerID"`
|
|
Type Type `json:"type,omitempty" gorm:"foreignKey:TypeID"`
|
|
Tasks []Task `json:"tasks,omitempty" gorm:"foreignKey:ProjectID"`
|
|
Members []User `json:"members,omitempty" gorm:"many2many:project_members;"`
|
|
}
|
|
|
|
// ProjectCreateRequest represents the request to create a new project
|
|
type ProjectCreateRequest struct {
|
|
Name string `json:"name" validate:"required,min=1,max=255"`
|
|
Description string `json:"description" validate:"max=1000"`
|
|
OwnerID string `json:"owner_id" validate:"required,uuid"`
|
|
TypeID string `json:"type_id" validate:"required,uuid"`
|
|
}
|
|
|
|
// ProjectUpdateRequest represents the request to update a project
|
|
type ProjectUpdateRequest struct {
|
|
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=255"`
|
|
Description *string `json:"description,omitempty" validate:"omitempty,max=1000"`
|
|
TypeID *string `json:"type_id,omitempty" validate:"omitempty,uuid"`
|
|
}
|
|
|
|
// ProjectInfo represents public project information
|
|
type ProjectInfo struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
OwnerID string `json:"owner_id"`
|
|
TypeID string `json:"type_id"`
|
|
Owner UserInfo `json:"owner,omitempty"`
|
|
Type TypeInfo `json:"type,omitempty"`
|
|
TaskCount int64 `json:"task_count"`
|
|
MemberCount int64 `json:"member_count"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
}
|
|
|
|
// ProjectMember represents the many-to-many relationship between projects and users
|
|
type ProjectMember struct {
|
|
ProjectID string `json:"project_id" gorm:"type:uuid;primaryKey"`
|
|
UserID string `json:"user_id" gorm:"type:uuid;primaryKey"`
|
|
RoleID string `json:"role_id" gorm:"type:uuid;not null;references:roles(id)"`
|
|
Project Project `json:"project,omitempty" gorm:"foreignKey:ProjectID"`
|
|
User User `json:"user,omitempty" gorm:"foreignKey:UserID"`
|
|
Role Role `json:"role,omitempty" gorm:"foreignKey:RoleID"`
|
|
}
|
|
|
|
// BeforeCreate is called before creating a project
|
|
func (p *Project) BeforeCreate(tx *gorm.DB) error {
|
|
p.BaseModel.BeforeCreate()
|
|
|
|
// Normalize name and description
|
|
p.Name = strings.TrimSpace(p.Name)
|
|
p.Description = strings.TrimSpace(p.Description)
|
|
|
|
return p.Validate()
|
|
}
|
|
|
|
// BeforeUpdate is called before updating a project
|
|
func (p *Project) BeforeUpdate(tx *gorm.DB) error {
|
|
p.BaseModel.BeforeUpdate()
|
|
|
|
// Normalize fields if they're being updated
|
|
if p.Name != "" {
|
|
p.Name = strings.TrimSpace(p.Name)
|
|
}
|
|
if p.Description != "" {
|
|
p.Description = strings.TrimSpace(p.Description)
|
|
}
|
|
|
|
return p.Validate()
|
|
}
|
|
|
|
// Validate validates project data
|
|
func (p *Project) Validate() error {
|
|
if p.Name == "" {
|
|
return errors.New("name is required")
|
|
}
|
|
|
|
if len(p.Name) > 255 {
|
|
return errors.New("name must not exceed 255 characters")
|
|
}
|
|
|
|
if p.OwnerID == "" {
|
|
return errors.New("owner_id is required")
|
|
}
|
|
|
|
if p.TypeID == "" {
|
|
return errors.New("type_id is required")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ToProjectInfo converts Project to ProjectInfo (public information)
|
|
func (p *Project) ToProjectInfo() ProjectInfo {
|
|
projectInfo := ProjectInfo{
|
|
ID: p.ID,
|
|
Name: p.Name,
|
|
Description: p.Description,
|
|
OwnerID: p.OwnerID,
|
|
TypeID: p.TypeID,
|
|
CreatedAt: p.CreatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
|
UpdatedAt: p.UpdatedAt.Format("2006-01-02T15:04:05Z07:00"),
|
|
}
|
|
|
|
// Add owner info if loaded
|
|
if p.Owner.ID != "" {
|
|
projectInfo.Owner = p.Owner.ToUserInfo()
|
|
}
|
|
|
|
// Add type info if loaded
|
|
if p.Type.ID != "" {
|
|
projectInfo.Type = p.Type.ToTypeInfo()
|
|
}
|
|
|
|
return projectInfo
|
|
}
|
|
|
|
// HasMember checks if a user is a member of the project
|
|
func (p *Project) HasMember(userID string) bool {
|
|
for _, member := range p.Members {
|
|
if member.ID == userID {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsOwner checks if a user is the owner of the project
|
|
func (p *Project) IsOwner(userID string) bool {
|
|
return p.OwnerID == userID
|
|
}
|