Skip to content

Commit 263160e

Browse files
committed
feat: add 'Receipts' to test CRUD w/o auth
1 parent aab0680 commit 263160e

File tree

8 files changed

+270
-13
lines changed

8 files changed

+270
-13
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
+/database
1+
database/
2+
portainer-data/

config/database-config.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func SetupDatabaseConnection() *gorm.DB {
2929
panic("failed to connect to database")
3030
}
3131

32-
db.AutoMigrate(&entity.Book{}, &entity.User{})
32+
db.AutoMigrate(&entity.Book{}, &entity.User{}, &entity.Receipt{})
3333

3434
return db
3535
}

controller/receipt-controller.go

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package controller
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"strconv"
7+
8+
"github.com/gin-gonic/gin"
9+
"github.com/putukrisna6/golang-api/dto"
10+
"github.com/putukrisna6/golang-api/entity"
11+
"github.com/putukrisna6/golang-api/helper"
12+
"github.com/putukrisna6/golang-api/service"
13+
)
14+
15+
type ReceiptController interface {
16+
All(context *gin.Context)
17+
Show(context *gin.Context)
18+
Insert(context *gin.Context)
19+
Update(context *gin.Context)
20+
Delete(context *gin.Context)
21+
}
22+
23+
type receiptController struct {
24+
receiptService service.ReceiptService
25+
}
26+
27+
func NewReceiptController(receiptService service.ReceiptService) ReceiptController {
28+
return &receiptController{
29+
receiptService: receiptService,
30+
}
31+
}
32+
33+
func (c *receiptController) All(context *gin.Context) {
34+
var receipts []entity.Receipt = c.receiptService.All()
35+
res := helper.BuildValidResponse("OK", receipts)
36+
context.JSON(http.StatusOK, res)
37+
}
38+
39+
func (c *receiptController) Show(context *gin.Context) {
40+
id, err := strconv.ParseUint(context.Param("id"), 0, 0)
41+
if err != nil {
42+
res := helper.BuildErrorResponse("parameter ID must not be empty", err.Error(), helper.EmptyObj{})
43+
context.AbortWithStatusJSON(http.StatusBadRequest, res)
44+
return
45+
}
46+
47+
var receipt entity.Receipt = c.receiptService.Show(id)
48+
if (receipt == entity.Receipt{}) {
49+
res := helper.BuildErrorResponse("failed to retrieve Receipt", "no data with given receiptID", helper.EmptyObj{})
50+
context.AbortWithStatusJSON(http.StatusNotFound, res)
51+
return
52+
}
53+
54+
res := helper.BuildValidResponse("OK", receipt)
55+
context.JSON(http.StatusOK, res)
56+
}
57+
58+
func (c *receiptController) Insert(context *gin.Context) {
59+
var receiptCreateDTO dto.ReceiptCreateDTO
60+
errDTO := context.ShouldBind(&receiptCreateDTO)
61+
if errDTO != nil {
62+
res := helper.BuildErrorResponse("failed to process request", errDTO.Error(), helper.EmptyObj{})
63+
context.AbortWithStatusJSON(http.StatusBadRequest, res)
64+
return
65+
}
66+
67+
result := c.receiptService.Insert(receiptCreateDTO)
68+
response := helper.BuildValidResponse("OK", result)
69+
context.JSON(http.StatusCreated, response)
70+
}
71+
72+
func (c *receiptController) Update(context *gin.Context) {
73+
var receiptUpdateDTO dto.ReceiptUpdateDTO
74+
errDTO := context.ShouldBind(&receiptUpdateDTO)
75+
if errDTO != nil {
76+
res := helper.BuildErrorResponse("failed to process request", errDTO.Error(), helper.EmptyObj{})
77+
context.AbortWithStatusJSON(http.StatusBadRequest, res)
78+
return
79+
}
80+
81+
result := c.receiptService.Update(receiptUpdateDTO)
82+
response := helper.BuildValidResponse("OK", result)
83+
context.JSON(http.StatusOK, response)
84+
}
85+
86+
func (c *receiptController) Delete(context *gin.Context) {
87+
var receipt entity.Receipt
88+
id, err := strconv.ParseUint(context.Param("id"), 0, 0)
89+
if err != nil {
90+
res := helper.BuildErrorResponse("parameter ID must not be empty", err.Error(), helper.EmptyObj{})
91+
context.AbortWithStatusJSON(http.StatusBadRequest, res)
92+
return
93+
}
94+
95+
receipt.ID = id
96+
c.receiptService.Delete(receipt)
97+
message := fmt.Sprintf("Receipt with ID %v successfuly deleted", receipt.ID)
98+
res := helper.BuildValidResponse(message, helper.EmptyObj{})
99+
context.JSON(http.StatusOK, res)
100+
}

dto/receipt-dto.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package dto
2+
3+
type ReceiptCreateDTO struct {
4+
Amount uint `json:"amount" form:"amount" binding:"required"`
5+
Total float64 `json:"total" form:"total" binding:"required"`
6+
}
7+
8+
type ReceiptUpdateDTO struct {
9+
ID uint64 `json:"id" form:"id" binding:"required"`
10+
Amount uint `json:"amount" form:"amount"`
11+
Total float64 `json:"total" form:"total"`
12+
}

entity/receipt.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package entity
2+
3+
import "time"
4+
5+
type Receipt struct {
6+
ID uint64 `gorm:"primary_key:auto_increment" json:"id"`
7+
Amount uint `json:"amount"`
8+
Total float64 `json:"total"`
9+
CreatedAt time.Time `json:"createdAt"`
10+
UpdatedAt time.Time `json:"updatedAt"`
11+
}

repository/receipt-repository.go

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package repository
2+
3+
import (
4+
"github.com/putukrisna6/golang-api/entity"
5+
"gorm.io/gorm"
6+
)
7+
8+
type ReceiptRepository interface {
9+
InsertReceipt(receipt entity.Receipt) entity.Receipt
10+
UpdateReceipt(receipt entity.Receipt) entity.Receipt
11+
ShowReceipt(receiptID uint64) entity.Receipt
12+
DeleteReceipt(receipt entity.Receipt)
13+
AllReceipts() []entity.Receipt
14+
}
15+
16+
type receiptConnection struct {
17+
connection *gorm.DB
18+
}
19+
20+
func NewReceiptRepository(db *gorm.DB) ReceiptRepository {
21+
return &receiptConnection{
22+
connection: db,
23+
}
24+
}
25+
26+
func (db *receiptConnection) InsertReceipt(receipt entity.Receipt) entity.Receipt {
27+
db.connection.Save(&receipt)
28+
db.connection.Find(&receipt)
29+
return receipt
30+
}
31+
32+
func (db *receiptConnection) UpdateReceipt(receipt entity.Receipt) entity.Receipt {
33+
var tempReceipt entity.Receipt
34+
db.connection.Find(&tempReceipt, receipt.ID)
35+
36+
if receipt.Amount == 0 {
37+
receipt.Amount = tempReceipt.Amount
38+
}
39+
if receipt.Total == 0 {
40+
receipt.Total = tempReceipt.Total
41+
}
42+
43+
db.connection.Save(&receipt)
44+
return receipt
45+
}
46+
47+
func (db *receiptConnection) ShowReceipt(receiptID uint64) entity.Receipt {
48+
var receipt entity.Receipt
49+
db.connection.Find(&receipt, receiptID)
50+
return receipt
51+
}
52+
53+
func (db *receiptConnection) DeleteReceipt(receipt entity.Receipt) {
54+
db.connection.Delete(&receipt)
55+
}
56+
57+
func (db *receiptConnection) AllReceipts() []entity.Receipt {
58+
var receipts []entity.Receipt
59+
db.connection.Find(&receipts)
60+
return receipts
61+
}

server.go

+23-11
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,21 @@ import (
1212
)
1313

1414
var (
15-
db *gorm.DB = config.SetupDatabaseConnection()
16-
userRepository repository.UserRepository = repository.NewUserRepository(db)
17-
bookRepository repository.BookRepository = repository.NewBookRepository(db)
15+
db *gorm.DB = config.SetupDatabaseConnection()
16+
userRepository repository.UserRepository = repository.NewUserRepository(db)
17+
bookRepository repository.BookRepository = repository.NewBookRepository(db)
18+
receiptRepository repository.ReceiptRepository = repository.NewReceiptRepository(db)
1819

19-
jwtService service.JWTService = service.NewJWTService()
20-
authService service.AuthService = service.NewAuthService(userRepository)
21-
userService service.UserService = service.NewUserService(userRepository)
22-
bookService service.BookService = service.NewBookService(bookRepository)
20+
jwtService service.JWTService = service.NewJWTService()
21+
authService service.AuthService = service.NewAuthService(userRepository)
22+
userService service.UserService = service.NewUserService(userRepository)
23+
bookService service.BookService = service.NewBookService(bookRepository)
24+
receiptService service.ReceiptService = service.NewReceiptService(receiptRepository)
2325

24-
authController controller.AuthController = controller.NewAuthController(authService, jwtService)
25-
userController controller.UserController = controller.NewUserController(userService, jwtService)
26-
bookController controller.BookController = controller.NewBookController(bookService, jwtService)
26+
authController controller.AuthController = controller.NewAuthController(authService, jwtService)
27+
userController controller.UserController = controller.NewUserController(userService, jwtService)
28+
bookController controller.BookController = controller.NewBookController(bookService, jwtService)
29+
receiptController controller.ReceiptController = controller.NewReceiptController(receiptService)
2730
)
2831

2932
func main() {
@@ -55,10 +58,19 @@ func main() {
5558
bookRoutes.GET("/", bookController.All)
5659
bookRoutes.POST("/", bookController.Insert)
5760
bookRoutes.GET("/:id", bookController.Get)
58-
bookRoutes.PUT("/:id", bookController.Update)
61+
bookRoutes.PUT("/", bookController.Update)
5962
bookRoutes.DELETE("/:id", bookController.Delete)
6063
}
6164

65+
receiptRoutes := r.Group("api/receipts")
66+
{
67+
receiptRoutes.GET("/", receiptController.All)
68+
receiptRoutes.POST("/", receiptController.Insert)
69+
receiptRoutes.GET("/:id", receiptController.Show)
70+
receiptRoutes.PUT("/", receiptController.Update)
71+
receiptRoutes.DELETE("/:id", receiptController.Delete)
72+
}
73+
6274
r.GET("/", func(c *gin.Context) {
6375
c.JSON(200, gin.H{
6476
"message": "Hello, World",

service/receipt-service.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package service
2+
3+
import (
4+
"log"
5+
6+
"github.com/mashingan/smapping"
7+
"github.com/putukrisna6/golang-api/dto"
8+
"github.com/putukrisna6/golang-api/entity"
9+
"github.com/putukrisna6/golang-api/repository"
10+
)
11+
12+
type ReceiptService interface {
13+
Insert(r dto.ReceiptCreateDTO) entity.Receipt
14+
Update(r dto.ReceiptUpdateDTO) entity.Receipt
15+
Show(receiptID uint64) entity.Receipt
16+
Delete(r entity.Receipt)
17+
All() []entity.Receipt
18+
}
19+
20+
type receiptService struct {
21+
receiptRepository repository.ReceiptRepository
22+
}
23+
24+
func NewReceiptService(receiptRepository repository.ReceiptRepository) ReceiptService {
25+
return &receiptService{
26+
receiptRepository: receiptRepository,
27+
}
28+
}
29+
30+
func (service *receiptService) Insert(r dto.ReceiptCreateDTO) entity.Receipt {
31+
newReceipt := entity.Receipt{}
32+
err := smapping.FillStruct(&newReceipt, smapping.MapFields(&r))
33+
if err != nil {
34+
log.Fatalf("failed to map: %v", err.Error())
35+
}
36+
37+
return service.receiptRepository.InsertReceipt(newReceipt)
38+
}
39+
40+
func (service *receiptService) Update(r dto.ReceiptUpdateDTO) entity.Receipt {
41+
receipt := entity.Receipt{}
42+
err := smapping.FillStruct(&receipt, smapping.MapFields(&r))
43+
if err != nil {
44+
log.Fatalf("failed to map: %v", err.Error())
45+
}
46+
47+
return service.receiptRepository.UpdateReceipt(receipt)
48+
}
49+
50+
func (service *receiptService) Show(receiptID uint64) entity.Receipt {
51+
return service.receiptRepository.ShowReceipt(receiptID)
52+
}
53+
54+
func (service *receiptService) Delete(receipt entity.Receipt) {
55+
service.receiptRepository.DeleteReceipt(receipt)
56+
}
57+
58+
func (service *receiptService) All() []entity.Receipt {
59+
return service.receiptRepository.AllReceipts()
60+
}

0 commit comments

Comments
 (0)