backend/pkg/post/domain/entity/post.go

157 lines
4.4 KiB
Go
Raw Permalink Normal View History

2025-11-19 05:33:06 +00:00
package entity
import (
"errors"
"time"
"backend/pkg/post/domain/post"
"github.com/gocql/gocql"
)
// Post represents a post entity in the system.
// It contains the main content and metadata for user posts.
type Post struct {
ID gocql.UUID `db:"id" partition_key:"true"` // Post unique identifier
AuthorUID string `db:"author_uid"` // Author user UID
Title string `db:"title"` // Post title
Content string `db:"content"` // Post content
Type post.Type `db:"type"` // Post type (text, image, video, etc.)
Status post.Status `db:"status"` // Post status (draft, published, etc.)
CategoryID *gocql.UUID `db:"category_id,omitempty"` // Category ID (optional)
Tags []string `db:"tags,omitempty"` // Post tags
Images []string `db:"images,omitempty"` // Image URLs (optional)
VideoURL *string `db:"video_url,omitempty"` // Video URL (optional)
LinkURL *string `db:"link_url,omitempty"` // Link URL (optional)
LikeCount int64 `db:"like_count"` // Number of likes
CommentCount int64 `db:"comment_count"` // Number of comments
ViewCount int64 `db:"view_count"` // Number of views
IsPinned bool `db:"is_pinned"` // Whether the post is pinned
PinnedAt *int64 `db:"pinned_at,omitempty"` // Pinned timestamp (optional)
PublishedAt *int64 `db:"published_at,omitempty"` // Published timestamp (optional)
CreatedAt int64 `db:"created_at"` // Creation timestamp
UpdatedAt int64 `db:"updated_at"` // Last update timestamp
}
// TableName returns the Cassandra table name for Post entities.
func (p *Post) TableName() string {
return "posts"
}
// Validate validates the Post entity
func (p *Post) Validate() error {
if p.AuthorUID == "" {
return errors.New("author_uid is required")
}
if len(p.Title) < 1 || len(p.Title) > 200 {
return errors.New("title length must be between 1 and 200 characters")
}
if len(p.Content) < 1 || len(p.Content) > 10000 {
return errors.New("content length must be between 1 and 10000 characters")
}
if !p.Type.IsValid() {
return errors.New("invalid post type")
}
if !p.Status.IsValid() {
return errors.New("invalid post status")
}
if len(p.Tags) > 10 {
return errors.New("maximum 10 tags allowed per post")
}
return nil
}
// SetTimestamps sets the create and update timestamps
func (p *Post) SetTimestamps() {
now := time.Now().UTC().UnixNano() / 1e6 // milliseconds
if p.CreatedAt == 0 {
p.CreatedAt = now
}
p.UpdatedAt = now
}
// IsNew returns true if this is a new post (no ID set)
func (p *Post) IsNew() bool {
var zeroUUID gocql.UUID
return p.ID == zeroUUID
}
// Publish marks the post as published
func (p *Post) Publish() {
p.Status = post.PostStatusPublished
now := time.Now().UTC().UnixNano() / 1e6
p.PublishedAt = &now
p.SetTimestamps()
}
// Archive marks the post as archived
func (p *Post) Archive() {
p.Status = post.PostStatusArchived
p.SetTimestamps()
}
// Delete marks the post as deleted (soft delete)
func (p *Post) Delete() {
p.Status = post.PostStatusDeleted
p.SetTimestamps()
}
// IsVisible returns true if the post is visible to public
func (p *Post) IsVisible() bool {
return p.Status.IsVisible()
}
// IsEditable returns true if the post can be edited
func (p *Post) IsEditable() bool {
return p.Status.IsEditable()
}
// IncrementLikeCount increments the like count
func (p *Post) IncrementLikeCount() {
p.LikeCount++
p.SetTimestamps()
}
// DecrementLikeCount decrements the like count
func (p *Post) DecrementLikeCount() {
if p.LikeCount > 0 {
p.LikeCount--
p.SetTimestamps()
}
}
// IncrementCommentCount increments the comment count
func (p *Post) IncrementCommentCount() {
p.CommentCount++
p.SetTimestamps()
}
// DecrementCommentCount decrements the comment count
func (p *Post) DecrementCommentCount() {
if p.CommentCount > 0 {
p.CommentCount--
p.SetTimestamps()
}
}
// IncrementViewCount increments the view count
func (p *Post) IncrementViewCount() {
p.ViewCount++
p.SetTimestamps()
}
// Pin pins the post
func (p *Post) Pin() {
p.IsPinned = true
now := time.Now().UTC().UnixNano() / 1e6
p.PinnedAt = &now
p.SetTimestamps()
}
// Unpin unpins the post
func (p *Post) Unpin() {
p.IsPinned = false
p.PinnedAt = nil
p.SetTimestamps()
}