Skip to content

Commit cac4988

Browse files
committed
feat(image): add update image endpoint and logic
- Implemented UpdateImage handler for updating image files and metadata. - Added repository and usecase logic for updating image records in the database. - Registered new PUT /images/{id} route for authenticated users. - Updated domain interfaces to support image update operations. - Refactored event and registration logic for consistency and bug fixes.
1 parent 19c3185 commit cac4988

File tree

10 files changed

+229
-41
lines changed

10 files changed

+229
-41
lines changed

app/events/repository/get_events.go

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ import (
66
"github.com/hammer-code/lms-be/domain"
77
)
88

9-
func (repo *repository) GetEvents(ctx context.Context, filter domain.EventFilter) (tData int, data []domain.Event, err error) {
10-
db := repo.db.DB(ctx).Model(&domain.Event{})
9+
func (repo *repository) GetEvents(ctx context.Context, filter domain.EventFilter) (tData int, dataDTO []domain.EventDTO, err error) {
10+
11+
data := []domain.Event{}
12+
13+
db := repo.db.DB(ctx).Model(&data)
1114

1215
var totalData int64
1316

@@ -35,11 +38,39 @@ func (repo *repository) GetEvents(ctx context.Context, filter domain.EventFilter
3538

3639
err = db.Limit(filter.FilterPagination.GetLimit()).
3740
Offset(filter.FilterPagination.GetOffset()).
38-
Preload("Tags").Preload("Speakers").Find(&data).Error
41+
Preload("Tags").Preload("Speakers").Preload("Author").Find(&data).Error
3942
if err != nil {
4043
return
4144
}
4245

43-
return int(totalData), data, err
44-
}
46+
if err == nil {
47+
for _, d := range data {
48+
dataDTO = append(dataDTO, domain.EventDTO{
49+
ID: d.ID,
50+
Title: d.Title,
51+
Description: d.Description,
52+
Slug: d.Slug,
53+
Image: d.Image,
54+
Date: d.Date,
55+
Type: d.Type,
56+
Location: d.Location,
57+
Duration: d.Duration,
58+
Capacity: d.Capacity,
59+
Status: d.Status,
60+
Tags: d.Tags,
61+
Speakers: d.Speakers,
62+
SessionType: d.SessionType,
63+
RegistrationLink: d.RegistrationLink,
64+
Price: d.Price,
65+
ReservationStartDate: d.ReservationStartDate,
66+
ReservationEndDate: d.ReservationEndDate,
67+
Author: d.Author.Username,
68+
CreatedAt: d.CreatedAt,
69+
UpdatedAt: d.UpdatedAt,
70+
DeletedAt: d.DeletedAt,
71+
})
72+
}
73+
}
4574

75+
return int(totalData), dataDTO, err
76+
}

app/events/usecase/create_registration_event.go

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (uc usecase) CreateRegistrationEvent(ctx context.Context, payload domain.Re
5252
err = utils.NewInternalServerError(ctx, err)
5353
return domain.RegisterEventResponse{}, err
5454
}
55-
55+
5656
if dataImage.IsUsed {
5757
err = utils.NewNotFoundError(ctx, "image not exists", errors.New("image not exists"))
5858
return domain.RegisterEventResponse{}, err
@@ -125,10 +125,8 @@ func (uc usecase) CreateRegistrationEvent(ctx context.Context, payload domain.Re
125125

126126
// is free event or not
127127
status := "SUCCESS"
128-
upToYou := "registration success"
129128
if event.Price != 0.0 {
130129
status = "PENDING"
131-
upToYou = "new register"
132130
emailPayload.SendEmail(ctx)
133131
} else {
134132
logrus.Info("free event, send email registration success")
@@ -151,19 +149,14 @@ func (uc usecase) CreateRegistrationEvent(ctx context.Context, payload domain.Re
151149
}
152150

153151
err = uc.dbTX.StartTransaction(ctx, func(txCtx context.Context) error {
154-
155152

156153
rId, err := uc.repository.CreateRegistrationEvent(txCtx, domain.RegistrationEvent{
157-
OrderNo: orderNo,
158-
UserID: strconv.Itoa(userData.ID),
159-
EventID: event.ID,
160-
Name: userData.Username,
161-
Email: userData.Email,
162-
PhoneNumber: payload.PhoneNumber,
163-
Status: status,
164-
UpToYou: upToYou,
154+
OrderNo: orderNo,
155+
UserID: strconv.Itoa(userData.ID),
156+
EventID: event.ID,
157+
Status: status,
165158
ImageProofPayment: dataImage.FileName,
166-
PaymentDate: null.NewTime(time.Now(), true),
159+
PaymentDate: null.NewTime(time.Now(), true),
167160
})
168161

169162
if err != nil {
@@ -175,7 +168,7 @@ func (uc usecase) CreateRegistrationEvent(ctx context.Context, payload domain.Re
175168
_, err = uc.repository.CreateEventPay(txCtx, domain.EventPay{
176169
RegistrationEventID: rId,
177170
EventID: event.ID,
178-
OrderNO: orderNo,
171+
OrderNO: orderNo,
179172
ImageProofPayment: dataImage.FileName,
180173
NetAmount: payload.NetAmount,
181174
})

app/events/usecase/get_events.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/hammer-code/lms-be/utils"
1010
)
1111

12-
func (uc usecase) GetEvents(ctx context.Context, filter domain.EventFilter) (resp []domain.Event, pagination domain.Pagination, err error) {
12+
func (uc usecase) GetEvents(ctx context.Context, filter domain.EventFilter) (resp []domain.EventDTO, pagination domain.Pagination, err error) {
1313
tData, datas, err := uc.repository.GetEvents(ctx, filter)
1414
if err != nil {
1515
err = utils.NewInternalServerError(ctx, err)

app/events/usecase/pay_process.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"time"
1010

1111
"github.com/hammer-code/lms-be/domain"
12+
contextkey "github.com/hammer-code/lms-be/pkg/context_key"
1213
"github.com/hammer-code/lms-be/pkg/email"
1314
"github.com/hammer-code/lms-be/utils"
1415
"github.com/sirupsen/logrus"
@@ -21,7 +22,8 @@ func (uc usecase) PayProcess(ctx context.Context, payload domain.PayProcessPaylo
2122
return err
2223
}
2324

24-
logrus.Info("registration event: ", rEvent)
25+
userData := ctx.Value(contextkey.UserKey).(domain.User)
26+
2527
if rEvent.ID == 0 {
2628
err = utils.NewNotFoundError(ctx, "registration order not found", errors.New("registration order not found"))
2729
return err
@@ -48,7 +50,6 @@ func (uc usecase) PayProcess(ctx context.Context, payload domain.PayProcessPaylo
4850

4951
eventPay.Status = payload.Status
5052
rEvent.Status = payload.Status
51-
rEvent.UpToYou = payload.Note
5253

5354
err = uc.dbTX.StartTransaction(ctx, func(txCtx context.Context) error {
5455
err = uc.repository.UpdateEventPay(txCtx, eventPay)
@@ -117,12 +118,12 @@ func (uc usecase) PayProcess(ctx context.Context, payload domain.PayProcessPaylo
117118
if err := emailPayload.AddReceiver(
118119
ctx,
119120
email.Receiver{
120-
Email: rEvent.Email,
121+
Email: userData.Email,
121122
Data: map[string]interface{}{
122-
"name": rEvent.Name,
123+
"name": userData.Username,
123124
"title": event.Title,
124125
"price": event.Price,
125-
"email": rEvent.Email,
126+
"email": userData.Email,
126127
"order_no": rEvent.OrderNo,
127128
"status": payload.Status,
128129
"note": payload.Note,
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package http
2+
3+
import (
4+
"net/http"
5+
"strconv"
6+
"strings"
7+
8+
"github.com/gorilla/mux"
9+
"github.com/hammer-code/lms-be/domain"
10+
"github.com/hammer-code/lms-be/utils"
11+
)
12+
13+
func (h Handler) UpdateImage(w http.ResponseWriter, r *http.Request) {
14+
// Parse image ID from query or URL (misal: /images/{id})
15+
idStr := mux.Vars(r)["id"]
16+
if idStr == "" {
17+
utils.Response(domain.HttpResponse{
18+
Code: http.StatusBadRequest,
19+
Message: "missing image id",
20+
}, w)
21+
return
22+
}
23+
id, err := strconv.ParseUint(idStr, 10, 64)
24+
if err != nil {
25+
utils.Response(domain.HttpResponse{
26+
Code: http.StatusBadRequest,
27+
Message: "invalid image id",
28+
}, w)
29+
return
30+
}
31+
32+
// Parse multipart form
33+
err = r.ParseMultipartForm(10 << 20) // 10MB
34+
if err != nil {
35+
utils.Response(domain.HttpResponse{
36+
Code: http.StatusBadRequest,
37+
Message: "failed to parse form",
38+
}, w)
39+
return
40+
}
41+
file, header, err := r.FormFile("image")
42+
if err != nil {
43+
utils.Response(domain.HttpResponse{
44+
Code: http.StatusBadRequest,
45+
Message: "failed to get file",
46+
}, w)
47+
return
48+
}
49+
defer file.Close()
50+
51+
category := r.FormValue("category")
52+
if category == "" {
53+
category = "public"
54+
}
55+
56+
contentType := header.Header.Values("Content-Type")[0]
57+
contentFiles := strings.Split(contentType, "/")
58+
59+
upload := domain.UploadImage{
60+
File: file,
61+
Header: header,
62+
Category: category,
63+
ContentType: contentType,
64+
Format: contentFiles[1],
65+
Type: contentFiles[0],
66+
}
67+
68+
ctx := r.Context()
69+
err = h.usecase.UpdateImage(ctx, upload, uint(id))
70+
if err != nil {
71+
utils.Response(domain.HttpResponse{
72+
Code: http.StatusInternalServerError,
73+
Message: err.Error(),
74+
}, w)
75+
return
76+
}
77+
78+
utils.Response(domain.HttpResponse{
79+
Code: 200,
80+
Message: "Image updated successfully",
81+
}, w)
82+
}
83+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package repository
2+
3+
import (
4+
"context"
5+
6+
"github.com/hammer-code/lms-be/domain"
7+
"github.com/sirupsen/logrus"
8+
)
9+
10+
func (repo *repository) UpdateImage(ctx context.Context, img domain.Image) error {
11+
err := repo.db.DB(ctx).Model(&domain.Image{}).
12+
Where("id = ?", img.ID).
13+
Updates(map[string]interface{}{
14+
"file_name": img.FileName,
15+
"file_path": img.FilePath,
16+
"format": img.Format,
17+
"content_type": img.ContentType,
18+
}).Error
19+
if err != nil {
20+
logrus.Error("repo.UpdateImage : failed to update")
21+
return err
22+
}
23+
return nil
24+
}

app/images/usecase/update_image.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package usecase
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io"
7+
"os"
8+
"time"
9+
10+
"github.com/hammer-code/lms-be/domain"
11+
"github.com/hammer-code/lms-be/pkg/hash"
12+
"github.com/sirupsen/logrus"
13+
)
14+
15+
func (us *usecase) UpdateImage(ctx context.Context, payload domain.UploadImage, id uint) error {
16+
var filePath string
17+
hName := hash.GenerateHash(time.Now().Format("2006-01-02 15:04:05") + "Hammercode")
18+
uploadDir := "./uploads"
19+
if payload.UserID != "" {
20+
uploadDir = fmt.Sprintf("./uploads/%s", payload.UserID)
21+
}
22+
23+
// file path/category/type image
24+
uploadDir = fmt.Sprintf("%s/%s/%s", uploadDir, payload.Category, payload.Type)
25+
fileName := fmt.Sprintf("%s.%s", hName[0:15], payload.Format)
26+
filePath = fmt.Sprintf("%s/%s", uploadDir, fileName)
27+
28+
// Ensure the directory exists, create it if it doesn't
29+
if err := os.MkdirAll(uploadDir, os.ModePerm); err != nil {
30+
logrus.Error("Failed to create directory:", err)
31+
return err
32+
}
33+
34+
// Save the file to the uploads directory
35+
dst, err := os.Create(filePath)
36+
if err != nil {
37+
logrus.Error("failed to create file path")
38+
return err
39+
}
40+
defer dst.Close()
41+
42+
_, err = io.Copy(dst, payload.File)
43+
if err != nil {
44+
logrus.Error("failed to read all file")
45+
return err
46+
}
47+
48+
// Update data di database
49+
img := domain.Image{
50+
ID: id,
51+
FileName: fileName,
52+
FilePath: filePath,
53+
Format: payload.Format,
54+
ContentType: payload.ContentType,
55+
}
56+
57+
return us.imageRepo.UpdateImage(ctx, img)
58+
}

cmd/serve_http.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,30 +155,32 @@ func registerHandler(app app.App) *mux.Router {
155155
public.HandleFunc("/images", app.ImageHandler.UploadImage).Methods(http.MethodPost)
156156
public.HandleFunc("/blogs", app.BlogPostHandler.GetAllBlogPosts).Methods(http.MethodGet)
157157
public.HandleFunc("/blogs/{slug}", app.BlogPostHandler.GetDetailBlogPost).Methods(http.MethodGet)
158-
158+
159159
protectedV1Route := v1.NewRoute().Subrouter()
160160
protectedV1Route.Use(app.Middleware.AuthMiddleware(constants.RoleUser))
161-
161+
162162
protectedV1AdminRoute := v1.PathPrefix("/admin").Subrouter()
163163
protectedV1AdminRoute.Use(app.Middleware.AuthMiddleware(constants.RoleAdmin))
164-
164+
165165
protectedV1Route.HandleFunc("/users", app.UserHandler.GetUsers).Methods(http.MethodGet)
166166
protectedV1Route.HandleFunc("/user", app.UserHandler.GetUserProfile).Methods(http.MethodGet)
167167
protectedV1Route.HandleFunc("/logout", app.UserHandler.Logout).Methods(http.MethodPost)
168-
168+
169169
protectedV1Route.HandleFunc("/", app.UserHandler.GetUserById).Methods(http.MethodGet)
170170
protectedV1Route.HandleFunc("/update", app.UserHandler.UpdateProfileUser).Methods(http.MethodPut)
171171
protectedV1Route.HandleFunc("/delete", app.UserHandler.DeleteUser).Methods(http.MethodDelete)
172-
172+
173173
protectedV1Route.HandleFunc("/events", app.EventHandler.CreateEvent).Methods(http.MethodPost)
174174
protectedV1Route.HandleFunc("/events/registrations", app.EventHandler.RegisterEvent).Methods(http.MethodPost)
175175
protectedV1Route.HandleFunc("/events/registrations", app.EventHandler.ListRegistration).Methods(http.MethodGet)
176176
protectedV1Route.HandleFunc("/events/pays", app.EventHandler.ListEventPay).Methods(http.MethodGet)
177177
protectedV1Route.HandleFunc("/events/pays", app.EventHandler.PayProcess).Methods(http.MethodPost)
178+
protectedV1Route.HandleFunc("/events/pay", app.EventHandler.PayEvent).Methods(http.MethodPost)
178179
protectedV1Route.HandleFunc("/events/{id}", app.EventHandler.GetEventByID).Methods(http.MethodGet)
179180
protectedV1Route.HandleFunc("/events/registrations", app.EventHandler.RegisterEvent).Methods(http.MethodPost)
180181

181182
protectedV1Route.HandleFunc("/images", app.ImageHandler.UploadImage).Methods(http.MethodPost)
183+
protectedV1Route.HandleFunc("/images/{id}", app.ImageHandler.UpdateImage).Methods(http.MethodPut)
182184

183185
protectedV1Route.HandleFunc("/blogs", app.BlogPostHandler.CreateBlogPost).Methods(http.MethodPost)
184186
public.HandleFunc("/blogs", app.BlogPostHandler.GetAllBlogPosts).Methods(http.MethodGet)
@@ -187,7 +189,7 @@ func registerHandler(app app.App) *mux.Router {
187189
protectedV1Route.HandleFunc("/blogs/{id}", app.BlogPostHandler.DeleteBlogPost).Methods(http.MethodDelete)
188190

189191
protectedV1AdminRoute.HandleFunc("/events", app.EventHandler.CreateEvent).Methods(http.MethodPost)
190-
protectedV1AdminRoute.HandleFunc("/events", app.EventHandler.GetEvents).Methods(http.MethodGet)
192+
protectedV1Route.HandleFunc("/events", app.EventHandler.GetEvents).Methods(http.MethodGet)
191193
protectedV1AdminRoute.HandleFunc("/events/{id}", app.EventHandler.DeleteEvent).Methods(http.MethodDelete)
192194
protectedV1AdminRoute.HandleFunc("/events/{id}", app.EventHandler.GetDetail).Methods(http.MethodGet)
193195

0 commit comments

Comments
 (0)