Skip to content

Commit

Permalink
Merge pull request #22 from GenerateNU/adam-post-table-and-crud
Browse files Browse the repository at this point in the history
NOT YET
  • Loading branch information
adammotts authored Feb 27, 2024
2 parents c497a91 + ff020f4 commit 202601f
Show file tree
Hide file tree
Showing 7 changed files with 341 additions and 1 deletion.
1 change: 1 addition & 0 deletions backend/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func main() {
clerkClient := routes.SetupAuthRoutes(r, db)
routes.SetupUserRoutes(r, db, clerkClient)
routes.SetupETradeRoutes(r, db)
routes.SetupPostRoutes(r, db)
routes.SetupOnboardingRoutes(r, db)
routes.SetupFollowingRoutes(r, db)

Expand Down
186 changes: 186 additions & 0 deletions backend/src/controllers/post.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package controllers

import (
"net/http"
"strconv"

"backend/src/models"
"backend/src/services"

"github.com/gin-gonic/gin"
)

type PostController struct {
postService *services.PostService
}

func NewPostController(postService *services.PostService) *PostController {
return &PostController{
postService: postService,
}
}

// GetAllPosts godoc
//
// @Summary Gets all posts
// @Description Returns all posts
// @ID get-all-posts
// @Tags post
// @Produce json
// @Success 200 {object} []models.Post
// @Failure 404 {string} string "Failed to fetch posts"
// @Router /api/posts/ [get]
func (pc *PostController) GetAllPosts(c *gin.Context) {
posts, err := pc.postService.GetAllPosts()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch posts"})
return
}

c.JSON(http.StatusOK, posts)
}

// GetPostsByUserId godoc
//
// @Summary Gets posts by user ID
// @Description Returns all posts for a specific user by user ID
// @ID get-posts-by-user-id
// @Tags post
// @Produce json
// @Param userId path uint true "User ID"
// @Success 200 {object} []models.Post
// @Failure 404 {string} string "Failed to fetch posts"
// @Router /api/posts/user/{userId} [get]
func (pc *PostController) GetPostsByUserId(c *gin.Context) {
userId, err := strconv.ParseUint(c.Param("userId"), 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
return
}

posts, err := pc.postService.GetPostsByUserId(uint(userId))
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Failed to fetch posts"})
return
}

c.JSON(http.StatusOK, posts)
}

// CreatePost godoc
//
// @Summary Creates a post
// @Description Creates a post
// @ID create-post
// @Tags post
// @Accept json
// @Produce json
// @Param first_name body string true "First name of the post"
// @Param last_name body string true "Last name of the post"
// @Param postname body string true "Postname of the post"
// @Param email body string true "Email of the post"
// @Param password body string true "Password of the post"
// @Success 201 {object} models.Post
// @Failure 400 {string} string "Failed to create post"
// @Router /api/posts/ [post]
func (pc *PostController) CreatePost(c *gin.Context) {
var post models.Post
if err := c.ShouldBindJSON(&post); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
return
}

createdPost, err := pc.postService.CreatePost(&post)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to create post"})
return
}

c.JSON(http.StatusCreated, createdPost)
}

// GetPostById godoc
//
// @Summary Gets a post by id
// @Description Returns a post by id
// @ID get-post-by-id
// @Tags post
// @Produce json
// @Param id path int true "ID of the post"
// @Success 200 {object} models.Post
// @Failure 404 {string} string "Failed to fetch post"
// @Router /api/posts/{id} [get]
func (pc *PostController) GetPostById(c *gin.Context) {
id := c.Param("id")
postID, err := strconv.ParseUint(id, 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"})
return
}

post, err := pc.postService.GetPostById(uint(postID))
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Failed to fetch post"})
return
}

c.JSON(http.StatusOK, post)
}

// UpdatePostById godoc
//
// @Summary Updates a post by id
// @Description Updates a post by id
// @ID update-post-by-id
// @Tags post
// @Accept json
// @Produce json
// @Param id path int true "ID of the post"
// @Param first_name body string true "First name of the post"
// @Param last_name body string true "Last name of the post"
// @Param postname body string true "Postname of the post"
// @Param email body string true "Email of the post"
// @Param password body string true "Password of the post"
// @Success 200 {object} models.Post
// @Failure 400 {string} string "Failed to update post"
// @Router /api/posts/{id} [put]
func (pc *PostController) UpdatePostById(c *gin.Context) {
id := c.Param("id")
postID, _ := strconv.ParseUint(id, 10, 32)
var post *models.Post
if err := c.ShouldBindJSON(&post); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"})
return
}

updatedPost, err := pc.postService.UpdatePostById(uint(postID), post)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to update post"})
return
}

c.JSON(http.StatusOK, updatedPost)
}

// DeletePostById godoc
//
// @Summary Deletes a post by id
// @Description Deletes a post by id
// @ID delete-post-by-id
// @Tags post
// @Produce json
// @Param id path int true "ID of the post"
// @Success 200 {object} models.Post
// @Failure 404 {string} string "Failed to delete post"
// @Router /api/posts/{id} [delete]
func (pc *PostController) DeletePostById(c *gin.Context) {
id := c.Param("id")
postID, _ := strconv.ParseUint(id, 10, 32)
post, err := pc.postService.DeletePostById(uint(postID))
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Failed to delete post"})
return
}

c.JSON(http.StatusOK, post)
}
30 changes: 30 additions & 0 deletions backend/src/db/migrations/7_POST_V1.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
DROP TABLE IF EXISTS post_type_enum;
DROP TABLE IF EXISTS posts;

--Create post type table
CREATE TYPE post_type_enum AS ENUM (
'1 month summary',
'Recent trade',
'Share comment'
);

--Create post table
CREATE TABLE IF NOT EXISTS posts (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
post_type post_type_enum NOT NULL,
num_data FLOAT NOT NULL,
ticker_symbol VARCHAR(9),
time_stamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
comment TEXT NOT NULL,
title VARCHAR NOT NULL
);

INSERT INTO posts (user_id, post_type, num_data, ticker_symbol, comment, title)
VALUES
(1, '1 month summary', 100, 'AAPL', 'I made a 100% return on my investment in Apple this month!', 'Apple Investment'),
(1, 'Recent trade', 200, 'TSLA', 'I just bought 200 shares of Tesla!', 'Tesla Investment'),
(1, 'Share comment', 150, 'MSFT', 'I think Microsoft is a great company to invest in!', 'Microsoft Comment'),
(1, '1 month summary', 250, 'GOOGL', 'I made a 250% return on my investment in Google this month!', 'Google Investment'),
(1, 'Recent trade', 300, 'AMZN', 'I just bought 300 shares of Amazon!', 'Amazon Investment'),
(1, 'Share comment', 400, 'FB', 'I think Facebook is a great company to invest in!', 'Facebook Comment');
27 changes: 27 additions & 0 deletions backend/src/models/post.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package models

import (
"backend/src/types"
"time"
)

type PostType string

const (
ONE_MONTH_SUMMARY PostType = "1 month summary"
RECENT_TRADE PostType = "Recent trade"
SHARE_COMMENT PostType = "Share comment"
)

type Post struct {
types.Model
UserID uint `gorm:"not null" json:"user_id"`
User User `gorm:"foreignKey:UserID"`
PostType PostType `gorm:"type:post_type_enum;not null" json:"post_type"`
NumData float64 `gorm:"not null" json:"num_data"`
TickerSymbol string `gorm:"type:varchar(9);" json:"ticker_symbol"`
TimeStamp time.Time `gorm:"default:created_at" json:"time_stamp"`
Comment string `gorm:"not null" json:"comment"`
Title string `gorm:"not null" json:"title"`
}

1 change: 0 additions & 1 deletion backend/src/routes/etrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ func SetupETradeRoutes(router *gin.Engine, db *gorm.DB) {
etradeService := services.NewETradeService(db)
etradeController := controllers.NewETradeController(etradeService)


etradeRoutes := router.Group("/etrade")
{
etradeRoutes.GET("/redirect/:user_id", etradeController.GetRedirectURL)
Expand Down
24 changes: 24 additions & 0 deletions backend/src/routes/post.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package routes

import (
"backend/src/controllers"
"backend/src/services"

"github.com/gin-gonic/gin"
"gorm.io/gorm"
)

func SetupPostRoutes(router *gin.Engine, db *gorm.DB) {
postService := services.NewPostService(db)
postController := controllers.NewPostController(postService)

postRoutes := router.Group("/posts")
{
postRoutes.GET("/", postController.GetAllPosts)
postRoutes.GET("/user-posts/:userId", postController.GetPostsByUserId)
postRoutes.POST("/", postController.CreatePost)
postRoutes.GET("/:id", postController.GetPostById)
postRoutes.PUT("/:id", postController.UpdatePostById)
postRoutes.DELETE("/:id", postController.DeletePostById)
}
}
73 changes: 73 additions & 0 deletions backend/src/services/post.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package services

import (
"backend/src/models"

"gorm.io/gorm"
)

type PostService struct {
DB *gorm.DB
}

func NewPostService(db *gorm.DB) *PostService {
return &PostService{
DB: db,
}
}

func (ps *PostService) GetAllPosts() ([]models.Post, error) {
var posts []models.Post
if err := ps.DB.Find(&posts).Error; err != nil {
return nil, err
}
return posts, nil
}

func (ps *PostService) GetPostsByUserId(userId uint) ([]models.Post, error) {
var posts []models.Post
if err := ps.DB.Where("user_id = ?", userId).Find(&posts).Error; err != nil {
return nil, err
}
return posts, nil
}

//TODO: Add GetPostsFromFollowedUsers once Cam is done

func (ps *PostService) CreatePost(post *models.Post) (*models.Post, error) {
if err := ps.DB.Create(post).Error; err != nil {
return nil, err
}
return post, nil
}

func (ps *PostService) GetPostById(id uint) (*models.Post, error) {
post := &models.Post{}
if err := ps.DB.First(post, id).Error; err != nil {
return nil, err
}
return post, nil
}

func (ps *PostService) UpdatePostById(id uint, post *models.Post) (*models.Post, error) {
// Retrieve the existing post from the database
_, err := ps.GetPostById(id)
if err != nil {
return nil, err
}

// Save the updated post back to the database
if err := ps.DB.Save(post).Error; err != nil {
return nil, err
}

return post, nil
}

func (ps *PostService) DeletePostById(id uint) (*models.Post, error) {
post := &models.Post{}
if err := ps.DB.Delete(post, id).Error; err != nil {
return nil, err
}
return post, nil
}

0 comments on commit 202601f

Please sign in to comment.