Skip to content

Commit

Permalink
feat: post checkin api (#2)
Browse files Browse the repository at this point in the history
Feature: post checkin api
  • Loading branch information
xappyyy authored Dec 25, 2023
2 parents 73820e5 + c3c3ab5 commit e28bdec
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 102 deletions.
2 changes: 1 addition & 1 deletion config/config.local.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
database:
supabase:
host: 127.0.0.1
user: postgres
password: postgres
Expand Down
4 changes: 2 additions & 2 deletions src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/spf13/viper"
)

type DatabaseConfig struct {
type SupabaseConfig struct {
Host string `mapstructure:"host"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
Expand All @@ -18,7 +18,7 @@ type DatabaseConfig struct {
}

type Config struct {
Database DatabaseConfig
SupabaseConfig SupabaseConfig `mapstructure:"supabase"`
}

func New() (*Config, error) {
Expand Down
32 changes: 27 additions & 5 deletions src/controller/user/user_controller.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package controller

import (
"github.com/esc-chula/gearfest-backend/src/interfaces"
"github.com/esc-chula/gearfest-backend/src/domain"
"github.com/esc-chula/gearfest-backend/src/usecase"
"github.com/gin-gonic/gin"
)
Expand All @@ -10,12 +10,10 @@ type UserController struct {
UserUsecase usecase.UserUsecase
}

func NewUserController(sqlHandler interfaces.SqlHandler) *UserController {
func NewUserController(repository usecase.UserRepository) *UserController {
return &UserController{
UserUsecase: usecase.UserUsecase{
UserRepository: usecase.UserRepository{
SqlHandler: sqlHandler,
},
UserRepository: repository,
},
}
}
Expand All @@ -31,3 +29,27 @@ func (controller *UserController) GetUser(ctx *gin.Context) {
}
ctx.JSON(200, user)
}

func (controller *UserController) PostCheckin(ctx *gin.Context) {

//convert request into obj
var CheckinDTO domain.CreateCheckinDTO
err := ctx.ShouldBindJSON(&CheckinDTO)
if err != nil {
ctx.AbortWithStatusJSON(400, gin.H{
"Message": "Invalid JSON format",
})
return
}
//post the obj to db using userId,LocationId (checkInId auto gen)
newCheckin, err := controller.UserUsecase.Post(CheckinDTO)

if err != nil {
ctx.AbortWithStatusJSON(500, gin.H{
"Message": "Internal server error",
})

return
}
ctx.JSON(201, newCheckin)
}
6 changes: 0 additions & 6 deletions src/controller/user/user_dto.go

This file was deleted.

9 changes: 7 additions & 2 deletions src/domain/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ type User struct {
}

type Checkin struct {
CheckinID uint `gorm:"primaryKey;autoincrement"`
CheckinID uint `gorm:"primaryKey;autoincrement"`
UserID string
LocationID string
LocationID uint
}

type CreateCheckinDTO struct {
UserID string `json:"user_id" binding:"required"`
LocationID uint `json:"location_id" binding:"required"`
}
8 changes: 0 additions & 8 deletions src/interfaces/sql_handler.go

This file was deleted.

65 changes: 21 additions & 44 deletions src/server/database.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,30 @@
package server

import (
"github.com/esc-chula/gearfest-backend/src/interfaces"
"fmt"
"os"

"github.com/esc-chula/gearfest-backend/src/config"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)

type SqlHandler struct {
db *gorm.DB
}

func NewSqlHandler(db *gorm.DB) interfaces.SqlHandler {
SqlHandler := new(SqlHandler)
SqlHandler.db = db
return SqlHandler
}

//Create obj in database
func (handler *SqlHandler) Create(obj interface{}) error {
result := handler.db.Create(obj)
if result.Error != nil {
return result.Error
}
return nil
}

//Update column of obj in database with column_name and value
func (handler *SqlHandler) UpdateColumn(obj interface{}, column_name string, value interface{}) error {
result := handler.db.Model(&obj).Update(column_name, value)
if result.Error != nil {
return result.Error
}
return nil
}

//Get data of object by primary key
func (handler *SqlHandler) GetByPrimaryKey(obj interface{}) error {
result := handler.db.First(obj)
if result.Error != nil {
return result.Error
}
return nil
}
func LoadSupabase(config config.SupabaseConfig) *gorm.DB {
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=%s TimeZone=%s",
config.Host,
config.User,
config.Password,
config.DBName,
config.Port,
config.SSLMode,
config.Timezone,
)

//Get data of object with associations
func (handler *SqlHandler) GetWithAssociations(obj interface{}) error {
result := handler.db.Preload(clause.Associations).First(obj)
if result.Error != nil {
return result.Error
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Printf("Error connecting to the database: %v\n", err)
os.Exit(0)
}
return nil
db = db.Exec(fmt.Sprintf("SET search_path TO %s", config.Schema)).Session(&gorm.Session{})
return db
}
61 changes: 61 additions & 0 deletions src/server/repository/user_repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package repository

import (
"github.com/esc-chula/gearfest-backend/src/domain"
"gorm.io/gorm"
)

type UserRepository struct {
db *gorm.DB
}

func NewUserRepository(db *gorm.DB) *UserRepository {
return &UserRepository{
db: db,
}
}

// Create user in database
func (repo *UserRepository) CreateUser(user *domain.User) error {
result := repo.db.Create(user)
if result.Error != nil {
return result.Error
}
return nil
}

// Create checkin
func (repo *UserRepository) Checkin(checkin *domain.Checkin) error {
result := repo.db.Create(checkin)
if result.Error != nil {
return result.Error
}
return nil
}

// Update column of user in database with column_name and value
func (repo *UserRepository) UpdateColumn(user *domain.User, column_name string, value interface{}) error {
result := repo.db.Model(user).Update(column_name, value)
if result.Error != nil {
return result.Error
}
return nil
}

// Get user by id
func (repo *UserRepository) GetById(user *domain.User, id string) error {
result := repo.db.First(user, "user_id = ?", id)
if result.Error != nil {
return result.Error
}
return nil
}

// Get user with checkins
func (repo *UserRepository) GetWithCheckins(user *domain.User, id string) error {
result := repo.db.Model(&domain.User{}).Preload("Checkins").First(user, "user_id = ?", id)
if result.Error != nil {
return result.Error
}
return nil
}
17 changes: 11 additions & 6 deletions src/server/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@ package server

import (
controller "github.com/esc-chula/gearfest-backend/src/controller/user"
"github.com/esc-chula/gearfest-backend/src/interfaces"
"github.com/esc-chula/gearfest-backend/src/server/repository"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)

func loadRoutes(sqlHandler interfaces.SqlHandler) *gin.Engine {
func loadRoutes(db *gorm.DB) *gin.Engine {
g := gin.New()
loadUserRoutes(g, db)
return g
}

//user routes (need to refactor soon)
user_controller := controller.NewUserController(sqlHandler)
func loadUserRoutes(g *gin.Engine, db *gorm.DB) {
UserRepository := repository.NewUserRepository(db)
user_controller := controller.NewUserController(UserRepository)
g.GET("/user/:id", user_controller.GetUser)

return g
//post checkin route
g.POST("/user/checkin", user_controller.PostCheckin)
}
22 changes: 2 additions & 20 deletions src/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"time"

"github.com/esc-chula/gearfest-backend/src/config"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)

Expand All @@ -24,27 +23,10 @@ func New() *Server {
os.Exit(0)
}

dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=%s TimeZone=%s",
config.Database.Host,
config.Database.User,
config.Database.Password,
config.Database.DBName,
config.Database.Port,
config.Database.SSLMode,
config.Database.Timezone,
)

db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Printf("Error connecting to the database: %v\n", err)
os.Exit(0)
}
db = db.Exec(fmt.Sprintf("SET search_path TO %s", config.Database.Schema)).Session(&gorm.Session{})

sqlHandler := NewSqlHandler(db)
db := LoadSupabase(config.SupabaseConfig)

server := &Server{
router: loadRoutes(sqlHandler),
router: loadRoutes(db),
db: db,
}
return server
Expand Down
27 changes: 19 additions & 8 deletions src/usecase/user_usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,34 @@ package usecase

import (
"github.com/esc-chula/gearfest-backend/src/domain"
"github.com/esc-chula/gearfest-backend/src/interfaces"
)

type UserRepository struct {
interfaces.SqlHandler
type UserRepository interface {
CreateUser(*domain.User) error
Checkin(*domain.Checkin) error
UpdateColumn(*domain.User, string, interface{}) error
GetById(*domain.User, string) error
GetWithCheckins(*domain.User, string) error
}

type UserUsecase struct {
UserRepository UserRepository
}

func (usecase *UserUsecase) Get(id string) (domain.User, error) {
//pass user id so when send to UserRepository it'll find user with the id
user := domain.User{
UserID: id,
}
user := domain.User{}
//send the value by address to assign all other field to user that we have created
err := usecase.UserRepository.GetByPrimaryKey(&user)
err := usecase.UserRepository.GetById(&user, id)
return user, err
}

func (usecase *UserUsecase) Post(CheckinDTO domain.CreateCheckinDTO) (domain.Checkin, error) {

checkin := domain.Checkin{
UserID: CheckinDTO.UserID,
LocationID: CheckinDTO.LocationID,
}

err := usecase.UserRepository.Checkin(&checkin)
return checkin, err
}
11 changes: 11 additions & 0 deletions supabase/migrations/20231225005909_location_id.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
alter table "public"."checkins" drop constraint "unique_user_location";

drop index if exists "public"."unique_user_location";

alter table "public"."checkins" alter column "location_id" set data type bigint using "location_id"::bigint;

alter table "public"."checkins" add constraint "checkins_location_id_check" CHECK ((location_id >= 0)) not valid;

alter table "public"."checkins" validate constraint "checkins_location_id_check";


0 comments on commit e28bdec

Please sign in to comment.