Skip to content

Commit

Permalink
post & records logic
Browse files Browse the repository at this point in the history
  • Loading branch information
pieceowater committed Dec 24, 2024
1 parent ce88567 commit d481fc5
Show file tree
Hide file tree
Showing 7 changed files with 395 additions and 40 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.23.0
require (
ariga.io/atlas-provider-gorm v0.5.0
github.com/joho/godotenv v1.5.1
github.com/pieceowater-dev/lotof.atrace.proto v0.0.4
github.com/pieceowater-dev/lotof.atrace.proto v0.0.11
github.com/pieceowater-dev/lotof.lib.gossiper/v2 v2.0.9
google.golang.org/grpc v1.69.2
google.golang.org/protobuf v1.35.2
Expand Down
25 changes: 15 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ ariga.io/atlas-provider-gorm v0.5.0 h1:DqYNWroKUiXmx2N6nf/I9lIWu6fpgB6OQx/JoelCT
ariga.io/atlas-provider-gorm v0.5.0/go.mod h1:8m6+N6+IgWMzPcR63c9sNOBoxfNk6yV6txBZBrgLg1o=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/Azure/azure-sdk-for-go v56.3.0+incompatible h1:DmhwMrUIvpeoTDiWRDtNHqelNUd3Og8JCkrLHQK795c=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
Expand Down Expand Up @@ -50,6 +51,10 @@ github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw=
github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg=
github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
Expand Down Expand Up @@ -122,8 +127,8 @@ github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuV
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
Expand Down Expand Up @@ -151,10 +156,8 @@ github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/En
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pieceowater-dev/lotof.atrace.proto v0.0.4 h1:e8pM0CkhN1aP1gqyAmf5dXWEq1or7J9aflV22Zuldew=
github.com/pieceowater-dev/lotof.atrace.proto v0.0.4/go.mod h1:u7nd5W/Q8WFa+C72CQJLvD3+um6afR2QvjisUJpsU18=
github.com/pieceowater-dev/lotof.lib.gossiper/v2 v2.0.3 h1:YqSOy95Tzw80/MFCRmJwhhOWD2JrAC9uzjbL9yNepSQ=
github.com/pieceowater-dev/lotof.lib.gossiper/v2 v2.0.3/go.mod h1:m/C+3z+Y2n9FPnakJl7jOl/4T1KfrE2/OhSslRKAGGc=
github.com/pieceowater-dev/lotof.atrace.proto v0.0.11 h1:zBiJ2NE5oHTvBcwTGbFLX+K50cw97JCV4VpFhkMbwWg=
github.com/pieceowater-dev/lotof.atrace.proto v0.0.11/go.mod h1:u7nd5W/Q8WFa+C72CQJLvD3+um6afR2QvjisUJpsU18=
github.com/pieceowater-dev/lotof.lib.gossiper/v2 v2.0.9 h1:hfU+DuDnYx6TiJNWG0gb85TNi9U3vtr/Q5AidHs3ZPs=
github.com/pieceowater-dev/lotof.lib.gossiper/v2 v2.0.9/go.mod h1:XLkDdT/Ll6bY0yTaNmx+rbNDgryvoJwDfg2I6I9cmQ0=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
Expand Down Expand Up @@ -201,6 +204,12 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE=
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY=
go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
Expand Down Expand Up @@ -304,12 +313,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
Expand Down
168 changes: 160 additions & 8 deletions internal/pkg/post/ctrl/post.ctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,187 @@ package ctrl

import (
pb "app/internal/core/grpc/generated"
"app/internal/pkg/post/ent"
"app/internal/pkg/post/svc"
"context"
"github.com/pieceowater-dev/lotof.lib.gossiper/v2"
)

type PostController struct {
postService *svc.PostService
pb.UnimplementedPostServiceServer
}

// NewPostController initializes a new PostController.
func NewPostController(service *svc.PostService) *PostController {
return &PostController{postService: service}
}

// GetPosts retrieves paginated posts based on filters.
func (p PostController) GetPosts(ctx context.Context, request *pb.GetPostsRequest) (*pb.GetPostsResponse, error) {
//TODO implement me
panic("implement me")
filter := gossiper.NewFilter[string](
request.GetSearch(),
gossiper.NewSort[string](
request.GetSort().GetField(),
gossiper.SortDirection(request.GetSort().GetDirection()),
),
gossiper.NewPagination(
int(request.GetPagination().GetPage()),
int(request.GetPagination().GetLength()),
),
)

paginatedResult, err := p.postService.GetPosts(ctx, filter)
if err != nil {
return nil, err
}

var posts []*pb.Post
for _, post := range paginatedResult.Rows {
posts = append(posts, &pb.Post{
Id: uint64(post.ID),
Title: post.Title,
Description: func() string {
if post.Description != nil {
return *post.Description
}
return ""
}(),
Location: func() *pb.PostLocation {
if post.Location != nil {
return &pb.PostLocation{
Comment: func() string {
if post.Location.Comment != nil {
return *post.Location.Comment
}
return ""
}(),
Country: post.Location.Country,
City: post.Location.City,
Address: post.Location.Address,
Latitude: float32(post.Location.Latitude),
Longitude: float32(post.Location.Longitude),
}
}
return nil
}(),
})
}

return &pb.GetPostsResponse{
Posts: posts,
PaginationInfo: &pb.PaginationInfo{
Count: int32(paginatedResult.Info.Count),
},
}, nil
}

// GetPost retrieves a single post by ID.
func (p PostController) GetPost(ctx context.Context, request *pb.GetPostRequest) (*pb.Post, error) {
//TODO implement me
panic("implement me")
post, err := p.postService.GetPost(ctx, int(request.Id))
if err != nil {
return nil, err
}

return &pb.Post{
Id: uint64(post.ID),
Title: post.Title,
Description: func() string {
if post.Description != nil {
return *post.Description
}
return ""
}(),
Location: func() *pb.PostLocation {
if post.Location != nil {
return &pb.PostLocation{
Comment: func() string {
if post.Location.Comment != nil {
return *post.Location.Comment
}
return ""
}(),
Country: post.Location.Country,
City: post.Location.City,
Address: post.Location.Address,
Latitude: float32(post.Location.Latitude),
Longitude: float32(post.Location.Longitude),
}
}
return nil
}(),
}, nil
}

// CreatePost creates a new post.
func (p PostController) CreatePost(ctx context.Context, request *pb.CreatePostRequest) (*pb.Post, error) {
//TODO implement me
panic("implement me")
post := &ent.Post{
Title: request.Title,
Description: &request.Description,
Phrase: request.Phrase,
Location: &ent.PostLocation{
Comment: &request.Location.Comment,
Country: request.Location.Country,
City: request.Location.City,
Address: request.Location.Address,
Latitude: float64(request.Location.Latitude),
Longitude: float64(request.Location.Longitude),
},
}

createdPost, err := p.postService.CreatePost(ctx, post)
if err != nil {
return nil, err
}

return &pb.Post{
Id: uint64(createdPost.ID),
Title: createdPost.Title,
Description: *createdPost.Description,
Location: &pb.PostLocation{
Comment: *createdPost.Location.Comment,
Country: createdPost.Location.Country,
City: createdPost.Location.City,
Address: createdPost.Location.Address,
Latitude: float32(createdPost.Location.Latitude),
Longitude: float32(createdPost.Location.Longitude),
},
}, nil
}

// DeletePost deletes a post by ID.
func (p PostController) DeletePost(ctx context.Context, request *pb.DeletePostRequest) (*pb.Post, error) {
//TODO implement me
panic("implement me")
deletedPost, err := p.postService.DeletePost(ctx, int(request.Id))
if err != nil {
return nil, err
}

return &pb.Post{
Id: uint64(deletedPost.ID),
Title: deletedPost.Title,
Description: func() string {
if deletedPost.Description != nil {
return *deletedPost.Description
}
return ""
}(),
Location: func() *pb.PostLocation {
if deletedPost.Location != nil {
return &pb.PostLocation{
Comment: func() string {
if deletedPost.Location.Comment != nil {
return *deletedPost.Location.Comment
}
return ""
}(),
Country: deletedPost.Location.Country,
City: deletedPost.Location.City,
Address: deletedPost.Location.Address,
Latitude: float32(deletedPost.Location.Latitude),
Longitude: float32(deletedPost.Location.Longitude),
}
}
return nil
}(),
}, nil
}
6 changes: 3 additions & 3 deletions internal/pkg/post/ent/post.ent.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import (
type Post struct {
gorm.Model
Title string `gorm:"not null"` // Title is required, e.g., "Master Door"
Description string // Optional description, e.g., "office main entrance"
Description *string // Optional description, e.g., "office main entrance"
Phrase string // Optional secret phrase, like an admin password
Location *PostLocation `gorm:"constraint:OnDelete:CASCADE"` // One-to-One optional relation
Location *PostLocation `gorm:"foreignKey:PostID;constraint:OnDelete:CASCADE"` // One-to-One optional relation
Records []ent.Record `gorm:"foreignKey:PostID;constraint:OnDelete:CASCADE"` // One Post has many Records
}

// PostLocation provides additional location-related metadata for a Post.
type PostLocation struct {
gorm.Model
PostID uint `gorm:"not null;uniqueIndex"` // Foreign key to Post, one-to-one relation
Comment string // Optional comment, e.g., "Door code is 0808#"
Comment *string // Optional comment, e.g., "Door code is 0808#"
Country string // Country code, e.g., KZ, US
City string // City name, e.g., Almaty
Address string // Main address, e.g., Some st. 21
Expand Down
65 changes: 56 additions & 9 deletions internal/pkg/post/svc/post.svc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,80 @@ package svc
import (
"app/internal/pkg/post/ent"
"context"
"fmt"
gossiper "github.com/pieceowater-dev/lotof.lib.gossiper/v2"
)

type PostService struct {
db gossiper.Database
}

// NewPostService initializes a new PostService.
func NewPostService(db gossiper.Database) *PostService {
return &PostService{db: db}
}

func (s PostService) GetPosts(ctx context.Context, filter gossiper.Filter[string]) (gossiper.PaginatedResult[*ent.Post], error) {
//TODO implement me
panic("implement me")
// GetPosts retrieves paginated posts from the database.
func (s PostService) GetPosts(ctx context.Context, filter gossiper.Filter[string]) (gossiper.PaginatedResult[ent.Post], error) {
var posts []ent.Post
var count int64

query := s.db.GetDB().Model(&ent.Post{}).Preload("Location")

// Apply search filters
if filter.Search != "" {
search := "%" + filter.Search + "%"
query = query.Where("title LIKE ? OR description LIKE ?", search, search)
}

// Count total records
if err := query.Count(&count).Error; err != nil {
return gossiper.PaginatedResult[ent.Post]{}, fmt.Errorf("failed to count posts: %w", err)
}

// Apply pagination
query = query.Offset((filter.Pagination.Page - 1) * filter.Pagination.Length).Limit(filter.Pagination.Length)

// Apply sorting dynamically
if field := filter.Sort.Field; field != "" && gossiper.IsFieldValid(&ent.Post{}, field) {
query = query.Order(fmt.Sprintf("%s %s", gossiper.ToSnakeCase(field), filter.Sort.Direction))
}

// Fetch data
if err := query.Find(&posts).Error; err != nil {
return gossiper.PaginatedResult[ent.Post]{}, fmt.Errorf("failed to fetch posts: %w", err)
}

return gossiper.NewPaginatedResult(posts, int(count)), nil
}

// GetPost retrieves a single post by ID.
func (s PostService) GetPost(ctx context.Context, id int) (ent.Post, error) {
//TODO implement me
panic("implement me")
var post ent.Post
result := s.db.GetDB().Preload("Location").First(&post, "id = ?", id)
if result.Error != nil {
return ent.Post{}, result.Error
}
return post, nil
}

// CreatePost adds a new post to the database.
func (s PostService) CreatePost(ctx context.Context, post *ent.Post) (ent.Post, error) {
//TODO implement me
panic("implement me")
if err := s.db.GetDB().Create(post).Error; err != nil {
return ent.Post{}, err
}
return *post, nil
}

// DeletePost removes a post from the database by ID.
func (s PostService) DeletePost(ctx context.Context, id int) (ent.Post, error) {
//TODO implement me
panic("implement me")
var post ent.Post
result := s.db.GetDB().First(&post, "id = ?", id)
if result.Error != nil {
return ent.Post{}, result.Error
}
if err := s.db.GetDB().Delete(&post).Error; err != nil {
return ent.Post{}, err
}
return post, nil
}
Loading

0 comments on commit d481fc5

Please sign in to comment.