diff --git a/module/feature/challenge/handler/handler.go b/module/feature/challenge/handler/handler.go index 8ba4373..cfc3c54 100644 --- a/module/feature/challenge/handler/handler.go +++ b/module/feature/challenge/handler/handler.go @@ -37,10 +37,12 @@ func (h *ChallengeHandler) GetAllChallenges() echo.HandlerFunc { search := c.QueryParam("search") status := c.QueryParam("status") - if search != "" { + if search != "" && status != "" { + challenges, totalItems, err = h.service.GetChallengesBySearchAndStatus(page, perPage, search, status) + } else if search != "" { challenges, totalItems, err = h.service.GetChallengeByTitle(page, perPage, search) } else if status != "" { - challenges, totalItems, err = h.service.GetChallengeByStatus(pageConv, perPage, status) + challenges, totalItems, err = h.service.GetChallengeByStatus(page, perPage, status) } else { challenges, totalItems, err = h.service.GetAllChallenges(pageConv, perPage) } @@ -272,9 +274,14 @@ func (h *ChallengeHandler) GetAllSubmitChallengeForm() echo.HandlerFunc { var totalItems int64 var err error filterStatus := c.QueryParam("status") - - if filterStatus != "" { - participants, totalItems, err = h.service.GetSubmitChallengeFormByStatus(pageConv, perPage, filterStatus) + filterDate := c.QueryParam("date") + + if filterStatus != "" && filterDate != "" { + participants, totalItems, err = h.service.GetSubmitChallengeFormByStatusAndDate(page, perPage, filterStatus, filterDate) + } else if filterStatus != "" { + participants, totalItems, err = h.service.GetSubmitChallengeFormByStatus(page, perPage, filterStatus) + } else if filterDate != "" { + participants, totalItems, err = h.service.GetSubmitChallengeFormByDateRange(page, perPage, filterDate) } else { participants, totalItems, err = h.service.GetAllSubmitChallengeForm(pageConv, perPage) } diff --git a/module/feature/challenge/interface.go b/module/feature/challenge/interface.go index d2e0bd2..b2c8feb 100644 --- a/module/feature/challenge/interface.go +++ b/module/feature/challenge/interface.go @@ -1,6 +1,8 @@ package challenge import ( + "time" + "github.com/capstone-kelompok-7/backend-disappear/module/entities" "github.com/capstone-kelompok-7/backend-disappear/module/feature/challenge/dto" "github.com/labstack/echo/v4" @@ -25,6 +27,11 @@ type RepositoryChallengeInterface interface { GetSubmitChallengeFormById(id uint64) (*entities.ChallengeFormModels, error) UpdateSubmitChallengeForm(id uint64, updatedStatus dto.UpdateChallengeFormStatusRequest) (*entities.ChallengeFormModels, error) GetSubmitChallengeFormByUserAndChallenge(userID uint64) ([]*entities.ChallengeFormModels, error) + GetSubmitChallengeFormByDateRange(page, perpage int, startDate, endDate time.Time) ([]*entities.ChallengeFormModels, error) + GetTotalSubmitChallengeFormCountByDateRange(startDate, endDate time.Time) (int64, error) + GetSubmitChallengeFormByStatusAndDate(page, perPage int, filterStatus string, startDate, endDate time.Time) ([]*entities.ChallengeFormModels, error) + GetTotalSubmitChallengeFormCountByStatusAndDate(filterStatus string, startDate, endDate time.Time) (int64, error) + GetChallengesBySearchAndStatus(page, perPage int, search, status string) ([]*entities.ChallengeModels, int64, error) } type ServiceChallengeInterface interface { @@ -43,6 +50,9 @@ type ServiceChallengeInterface interface { GetSubmitChallengeFormByStatus(page, perPage int, status string) ([]*entities.ChallengeFormModels, int64, error) GetSubmitChallengeFormById(id uint64) (*entities.ChallengeFormModels, error) UpdateSubmitChallengeForm(id uint64, updatedStatus dto.UpdateChallengeFormStatusRequest) (*entities.ChallengeFormModels, error) + GetSubmitChallengeFormByDateRange(page, perPage int, filterType string) ([]*entities.ChallengeFormModels, int64, error) + GetSubmitChallengeFormByStatusAndDate(page, perPage int, filterStatus string, filterType string) ([]*entities.ChallengeFormModels, int64, error) + GetChallengesBySearchAndStatus(page, perPage int, search, status string) ([]*entities.ChallengeModels, int64, error) } type HandlerChallengeInterface interface { diff --git a/module/feature/challenge/mocks/RepositoryChallengeInterface.go b/module/feature/challenge/mocks/RepositoryChallengeInterface.go index ef6cfdb..2ce9553 100644 --- a/module/feature/challenge/mocks/RepositoryChallengeInterface.go +++ b/module/feature/challenge/mocks/RepositoryChallengeInterface.go @@ -7,6 +7,8 @@ import ( dto "github.com/capstone-kelompok-7/backend-disappear/module/feature/challenge/dto" mock "github.com/stretchr/testify/mock" + + time "time" ) // RepositoryChallengeInterface is an autogenerated mock type for the RepositoryChallengeInterface type @@ -210,6 +212,65 @@ func (_m *RepositoryChallengeInterface) GetChallengeById(id uint64) (*entities.C return r0, r1 } +// GetChallengesBySearchAndStatus provides a mock function with given fields: page, perPage, search, status +func (_m *RepositoryChallengeInterface) GetChallengesBySearchAndStatus(page int, perPage int, search string, status string) ([]*entities.ChallengeModels, int64, error) { + ret := _m.Called(page, perPage, search, status) + + var r0 []*entities.ChallengeModels + var r1 int64 + var r2 error + if rf, ok := ret.Get(0).(func(int, int, string, string) ([]*entities.ChallengeModels, int64, error)); ok { + return rf(page, perPage, search, status) + } + if rf, ok := ret.Get(0).(func(int, int, string, string) []*entities.ChallengeModels); ok { + r0 = rf(page, perPage, search, status) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*entities.ChallengeModels) + } + } + + if rf, ok := ret.Get(1).(func(int, int, string, string) int64); ok { + r1 = rf(page, perPage, search, status) + } else { + r1 = ret.Get(1).(int64) + } + + if rf, ok := ret.Get(2).(func(int, int, string, string) error); ok { + r2 = rf(page, perPage, search, status) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// GetSubmitChallengeFormByDateRange provides a mock function with given fields: page, perpage, startDate, endDate +func (_m *RepositoryChallengeInterface) GetSubmitChallengeFormByDateRange(page int, perpage int, startDate time.Time, endDate time.Time) ([]*entities.ChallengeFormModels, error) { + ret := _m.Called(page, perpage, startDate, endDate) + + var r0 []*entities.ChallengeFormModels + var r1 error + if rf, ok := ret.Get(0).(func(int, int, time.Time, time.Time) ([]*entities.ChallengeFormModels, error)); ok { + return rf(page, perpage, startDate, endDate) + } + if rf, ok := ret.Get(0).(func(int, int, time.Time, time.Time) []*entities.ChallengeFormModels); ok { + r0 = rf(page, perpage, startDate, endDate) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*entities.ChallengeFormModels) + } + } + + if rf, ok := ret.Get(1).(func(int, int, time.Time, time.Time) error); ok { + r1 = rf(page, perpage, startDate, endDate) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetSubmitChallengeFormById provides a mock function with given fields: id func (_m *RepositoryChallengeInterface) GetSubmitChallengeFormById(id uint64) (*entities.ChallengeFormModels, error) { ret := _m.Called(id) @@ -262,6 +323,32 @@ func (_m *RepositoryChallengeInterface) GetSubmitChallengeFormByStatus(page int, return r0, r1 } +// GetSubmitChallengeFormByStatusAndDate provides a mock function with given fields: page, perPage, filterStatus, startDate, endDate +func (_m *RepositoryChallengeInterface) GetSubmitChallengeFormByStatusAndDate(page int, perPage int, filterStatus string, startDate time.Time, endDate time.Time) ([]*entities.ChallengeFormModels, error) { + ret := _m.Called(page, perPage, filterStatus, startDate, endDate) + + var r0 []*entities.ChallengeFormModels + var r1 error + if rf, ok := ret.Get(0).(func(int, int, string, time.Time, time.Time) ([]*entities.ChallengeFormModels, error)); ok { + return rf(page, perPage, filterStatus, startDate, endDate) + } + if rf, ok := ret.Get(0).(func(int, int, string, time.Time, time.Time) []*entities.ChallengeFormModels); ok { + r0 = rf(page, perPage, filterStatus, startDate, endDate) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*entities.ChallengeFormModels) + } + } + + if rf, ok := ret.Get(1).(func(int, int, string, time.Time, time.Time) error); ok { + r1 = rf(page, perPage, filterStatus, startDate, endDate) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetSubmitChallengeFormByUserAndChallenge provides a mock function with given fields: userID func (_m *RepositoryChallengeInterface) GetSubmitChallengeFormByUserAndChallenge(userID uint64) ([]*entities.ChallengeFormModels, error) { ret := _m.Called(userID) @@ -384,6 +471,30 @@ func (_m *RepositoryChallengeInterface) GetTotalSubmitChallengeFormCount() (int6 return r0, r1 } +// GetTotalSubmitChallengeFormCountByDateRange provides a mock function with given fields: startDate, endDate +func (_m *RepositoryChallengeInterface) GetTotalSubmitChallengeFormCountByDateRange(startDate time.Time, endDate time.Time) (int64, error) { + ret := _m.Called(startDate, endDate) + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(time.Time, time.Time) (int64, error)); ok { + return rf(startDate, endDate) + } + if rf, ok := ret.Get(0).(func(time.Time, time.Time) int64); ok { + r0 = rf(startDate, endDate) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(time.Time, time.Time) error); ok { + r1 = rf(startDate, endDate) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetTotalSubmitChallengeFormCountByStatus provides a mock function with given fields: status func (_m *RepositoryChallengeInterface) GetTotalSubmitChallengeFormCountByStatus(status string) (int64, error) { ret := _m.Called(status) @@ -408,6 +519,30 @@ func (_m *RepositoryChallengeInterface) GetTotalSubmitChallengeFormCountByStatus return r0, r1 } +// GetTotalSubmitChallengeFormCountByStatusAndDate provides a mock function with given fields: filterStatus, startDate, endDate +func (_m *RepositoryChallengeInterface) GetTotalSubmitChallengeFormCountByStatusAndDate(filterStatus string, startDate time.Time, endDate time.Time) (int64, error) { + ret := _m.Called(filterStatus, startDate, endDate) + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(string, time.Time, time.Time) (int64, error)); ok { + return rf(filterStatus, startDate, endDate) + } + if rf, ok := ret.Get(0).(func(string, time.Time, time.Time) int64); ok { + r0 = rf(filterStatus, startDate, endDate) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(string, time.Time, time.Time) error); ok { + r1 = rf(filterStatus, startDate, endDate) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // UpdateChallenge provides a mock function with given fields: id, updatedChallenge func (_m *RepositoryChallengeInterface) UpdateChallenge(id uint64, updatedChallenge *entities.ChallengeModels) (*entities.ChallengeModels, error) { ret := _m.Called(id, updatedChallenge) diff --git a/module/feature/challenge/mocks/ServiceChallengeInterface.go b/module/feature/challenge/mocks/ServiceChallengeInterface.go index ea31aaa..23dba10 100644 --- a/module/feature/challenge/mocks/ServiceChallengeInterface.go +++ b/module/feature/challenge/mocks/ServiceChallengeInterface.go @@ -262,6 +262,39 @@ func (_m *ServiceChallengeInterface) GetChallengeByTitle(page int, perPage int, return r0, r1, r2 } +// GetChallengesBySearchAndStatus provides a mock function with given fields: page, perPage, search, status +func (_m *ServiceChallengeInterface) GetChallengesBySearchAndStatus(page int, perPage int, search string, status string) ([]*entities.ChallengeModels, int64, error) { + ret := _m.Called(page, perPage, search, status) + + var r0 []*entities.ChallengeModels + var r1 int64 + var r2 error + if rf, ok := ret.Get(0).(func(int, int, string, string) ([]*entities.ChallengeModels, int64, error)); ok { + return rf(page, perPage, search, status) + } + if rf, ok := ret.Get(0).(func(int, int, string, string) []*entities.ChallengeModels); ok { + r0 = rf(page, perPage, search, status) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*entities.ChallengeModels) + } + } + + if rf, ok := ret.Get(1).(func(int, int, string, string) int64); ok { + r1 = rf(page, perPage, search, status) + } else { + r1 = ret.Get(1).(int64) + } + + if rf, ok := ret.Get(2).(func(int, int, string, string) error); ok { + r2 = rf(page, perPage, search, status) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + // GetNextPage provides a mock function with given fields: currentPage, totalPages func (_m *ServiceChallengeInterface) GetNextPage(currentPage int, totalPages int) int { ret := _m.Called(currentPage, totalPages) @@ -290,6 +323,39 @@ func (_m *ServiceChallengeInterface) GetPrevPage(currentPage int) int { return r0 } +// GetSubmitChallengeFormByDateRange provides a mock function with given fields: page, perPage, filterType +func (_m *ServiceChallengeInterface) GetSubmitChallengeFormByDateRange(page int, perPage int, filterType string) ([]*entities.ChallengeFormModels, int64, error) { + ret := _m.Called(page, perPage, filterType) + + var r0 []*entities.ChallengeFormModels + var r1 int64 + var r2 error + if rf, ok := ret.Get(0).(func(int, int, string) ([]*entities.ChallengeFormModels, int64, error)); ok { + return rf(page, perPage, filterType) + } + if rf, ok := ret.Get(0).(func(int, int, string) []*entities.ChallengeFormModels); ok { + r0 = rf(page, perPage, filterType) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*entities.ChallengeFormModels) + } + } + + if rf, ok := ret.Get(1).(func(int, int, string) int64); ok { + r1 = rf(page, perPage, filterType) + } else { + r1 = ret.Get(1).(int64) + } + + if rf, ok := ret.Get(2).(func(int, int, string) error); ok { + r2 = rf(page, perPage, filterType) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + // GetSubmitChallengeFormById provides a mock function with given fields: id func (_m *ServiceChallengeInterface) GetSubmitChallengeFormById(id uint64) (*entities.ChallengeFormModels, error) { ret := _m.Called(id) @@ -349,6 +415,39 @@ func (_m *ServiceChallengeInterface) GetSubmitChallengeFormByStatus(page int, pe return r0, r1, r2 } +// GetSubmitChallengeFormByStatusAndDate provides a mock function with given fields: page, perPage, filterStatus, filterType +func (_m *ServiceChallengeInterface) GetSubmitChallengeFormByStatusAndDate(page int, perPage int, filterStatus string, filterType string) ([]*entities.ChallengeFormModels, int64, error) { + ret := _m.Called(page, perPage, filterStatus, filterType) + + var r0 []*entities.ChallengeFormModels + var r1 int64 + var r2 error + if rf, ok := ret.Get(0).(func(int, int, string, string) ([]*entities.ChallengeFormModels, int64, error)); ok { + return rf(page, perPage, filterStatus, filterType) + } + if rf, ok := ret.Get(0).(func(int, int, string, string) []*entities.ChallengeFormModels); ok { + r0 = rf(page, perPage, filterStatus, filterType) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*entities.ChallengeFormModels) + } + } + + if rf, ok := ret.Get(1).(func(int, int, string, string) int64); ok { + r1 = rf(page, perPage, filterStatus, filterType) + } else { + r1 = ret.Get(1).(int64) + } + + if rf, ok := ret.Get(2).(func(int, int, string, string) error); ok { + r2 = rf(page, perPage, filterStatus, filterType) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + // UpdateChallenge provides a mock function with given fields: id, updatedChallenge func (_m *ServiceChallengeInterface) UpdateChallenge(id uint64, updatedChallenge *entities.ChallengeModels) (*entities.ChallengeModels, error) { ret := _m.Called(id, updatedChallenge) diff --git a/module/feature/challenge/repository/repository.go b/module/feature/challenge/repository/repository.go index 44e9b34..c2eae16 100644 --- a/module/feature/challenge/repository/repository.go +++ b/module/feature/challenge/repository/repository.go @@ -51,6 +51,18 @@ func (r *ChallengeRepository) GetTotalChallengeCountByTitle(title string) (int64 return count, err } +// func (r *CarouselRepository) GetTotalCarouselCountByName(name string) (int64, error) { +// var count int64 +// query := r.db.Model(&entities.CarouselModels{}).Where("deleted_at IS NULL") + +// if name != "" { +// query = query.Where("name LIKE ?", "%"+name+"%") +// } + +// err := query.Count(&count).Error +// return count, err +// } + func (r *ChallengeRepository) FindByStatus(page, perpage int, status string) ([]*entities.ChallengeModels, error) { var challenge []*entities.ChallengeModels offset := (page - 1) * perpage @@ -173,3 +185,71 @@ func (r *ChallengeRepository) GetSubmitChallengeFormByUserAndChallenge(userID ui } return submissions, nil } + +func (r *ChallengeRepository) GetSubmitChallengeFormByDateRange(page, perpage int, startDate, endDate time.Time) ([]*entities.ChallengeFormModels, error) { + var participant []*entities.ChallengeFormModels + offset := (page - 1) * perpage + if err := r.db.Where("created_at BETWEEN ? AND ? AND deleted_at IS NULL", startDate, endDate).Offset(offset).Limit(perpage).Find(&participant).Error; err != nil { + return nil, err + } + return participant, nil +} + +func (r *ChallengeRepository) GetTotalSubmitChallengeFormCountByDateRange(startDate, endDate time.Time) (int64, error) { + var count int64 + err := r.db.Model(&entities.ChallengeFormModels{}).Where("created_at BETWEEN ? AND ? AND deleted_at IS NULL", startDate, endDate).Count(&count).Error + return count, err +} + +func (r *ChallengeRepository) GetSubmitChallengeFormByStatusAndDate(page, perPage int, filterStatus string, startDate, endDate time.Time) ([]*entities.ChallengeFormModels, error) { + var participants []*entities.ChallengeFormModels + offset := (page - 1) * perPage + + err := r.db.Where("status = ? AND created_at BETWEEN ? AND ? AND deleted_at IS NULL", filterStatus, startDate, endDate). + Offset(offset). + Limit(perPage). + Find(&participants).Error + + if err != nil { + return nil, err + } + + return participants, nil +} + +func (r *ChallengeRepository) GetTotalSubmitChallengeFormCountByStatusAndDate(filterStatus string, startDate, endDate time.Time) (int64, error) { + var count int64 + err := r.db.Model(&entities.ChallengeFormModels{}). + Where("status = ? AND created_at BETWEEN ? AND ? AND deleted_at IS NULL", filterStatus, startDate, endDate). + Count(&count). + Error + + return count, err +} + +func (r *ChallengeRepository) GetChallengesBySearchAndStatus(page, perPage int, search, status string) ([]*entities.ChallengeModels, int64, error) { + var challenges []*entities.ChallengeModels + offset := (page - 1) * perPage + + db := r.db.Model(&entities.ChallengeModels{}).Where("deleted_at IS NULL") + + if search != "" { + db = db.Where("title LIKE ? ", "%"+search+"%") + } + + if status != "" { + db = db.Where("status = ? ", status) + } + + err := db.Offset(offset).Limit(perPage).Find(&challenges).Error + if err != nil { + return nil, 0, err + } + + var totalItems int64 + if err := db.Count(&totalItems).Error; err != nil { + return nil, 0, err + } + + return challenges, totalItems, nil +} diff --git a/module/feature/challenge/service/service.go b/module/feature/challenge/service/service.go index d501f9a..1c4695b 100644 --- a/module/feature/challenge/service/service.go +++ b/module/feature/challenge/service/service.go @@ -3,6 +3,7 @@ package service import ( "errors" "math" + "strings" "time" "github.com/capstone-kelompok-7/backend-disappear/module/entities" @@ -309,3 +310,78 @@ func (s *ChallengeService) GetSubmitChallengeFormById(id uint64) (*entities.Chal return result, nil } + +func getDatesFromFilterType(filterType string) (time.Time, time.Time, error) { + filterType = strings.ToLower(filterType) + now := time.Now() + var startDate, endDate time.Time + + switch filterType { + case "hari ini": + startDate = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.UTC) + endDate = startDate.Add(24 * time.Hour) + case "minggu ini": + startOfWeek := now.AddDate(0, 0, -int(now.Weekday())) + startDate = time.Date(startOfWeek.Year(), startOfWeek.Month(), startOfWeek.Day(), 0, 0, 0, 0, time.UTC) + endDate = startDate.AddDate(0, 0, 7) + case "bulan ini": + startDate = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.UTC) + nextMonth := startDate.AddDate(0, 1, 0) + endDate = nextMonth.Add(-time.Second) + case "tahun ini": + startDate = time.Date(now.Year(), 1, 1, 0, 0, 0, 0, time.UTC) + nextYear := startDate.AddDate(1, 0, 0) + endDate = nextYear.Add(-time.Second) + default: + return time.Time{}, time.Time{}, errors.New("tipe filter tidak valid") + } + + return startDate, endDate, nil +} + +func (s *ChallengeService) GetSubmitChallengeFormByDateRange(page, perPage int, filterType string) ([]*entities.ChallengeFormModels, int64, error) { + startDate, endDate, err := getDatesFromFilterType(filterType) + if err != nil { + return nil, 0, err + } + + result, err := s.repo.GetSubmitChallengeFormByDateRange(page, perPage, startDate, endDate) + if err != nil { + return nil, 0, errors.New("gagal mendapatkan form pengumpulan: " + err.Error()) + } + + totalItems, err := s.repo.GetTotalSubmitChallengeFormCountByDateRange(startDate, endDate) + if err != nil { + return nil, 0, errors.New("gagal mendapatkan total form pengumpulan: " + err.Error()) + } + + return result, totalItems, nil +} + +func (s *ChallengeService) GetSubmitChallengeFormByStatusAndDate(page, perPage int, filterStatus string, filterType string) ([]*entities.ChallengeFormModels, int64, error) { + startDate, endDate, err := getDatesFromFilterType(filterType) + if err != nil { + return nil, 0, err + } + + participants, err := s.repo.GetSubmitChallengeFormByStatusAndDate(page, perPage, filterStatus, startDate, endDate) + if err != nil { + return nil, 0, errors.New("gagal mendapatkan form pengumpulan: " + err.Error()) + } + + totalItems, err := s.repo.GetTotalSubmitChallengeFormCountByStatusAndDate(filterStatus, startDate, endDate) + if err != nil { + return nil, 0, errors.New("gagal mendapatkan total form pengumpulan: " + err.Error()) + } + + return participants, totalItems, nil +} + +func (s *ChallengeService) GetChallengesBySearchAndStatus(page, perPage int, search, status string) ([]*entities.ChallengeModels, int64, error) { + challenges, totalItems, err := s.repo.GetChallengesBySearchAndStatus(page, perPage, search, status) + if err != nil { + return nil, 0, errors.New("gagal mendapatkan tantangan: " + err.Error()) + } + + return challenges, totalItems, nil +} diff --git a/module/feature/product/handler/handler.go b/module/feature/product/handler/handler.go index ee67fb3..e151207 100644 --- a/module/feature/product/handler/handler.go +++ b/module/feature/product/handler/handler.go @@ -1,13 +1,14 @@ package handler import ( + "mime/multipart" + "strconv" + "github.com/capstone-kelompok-7/backend-disappear/module/entities" "github.com/capstone-kelompok-7/backend-disappear/module/feature/product" "github.com/capstone-kelompok-7/backend-disappear/module/feature/product/dto" "github.com/capstone-kelompok-7/backend-disappear/utils" "github.com/capstone-kelompok-7/backend-disappear/utils/upload" - "mime/multipart" - "strconv" "github.com/capstone-kelompok-7/backend-disappear/utils/response" "github.com/labstack/echo/v4" @@ -156,8 +157,14 @@ func (h *ProductHandler) GetAllProductsReview() echo.HandlerFunc { var totalItems int64 var err error search := c.QueryParam("search") - if search != "" { - products, totalItems, err = h.service.GetProductsByName(page, perPage, search) + filterRated := c.QueryParam("rating") + + if search != "" && filterRated != "" { + products, totalItems, err = h.service.SearchByNameAndFilterByRating(pageConv, perPage, search, filterRated) + } else if filterRated != "" { + products, totalItems, err = h.service.GetRatedProductsInRange(pageConv, perPage, filterRated) + } else if search != "" { + products, totalItems, err = h.service.GetProductsByName(pageConv, perPage, search) } else { products, totalItems, err = h.service.GetProductReviews(pageConv, perPage) } diff --git a/module/feature/product/interface.go b/module/feature/product/interface.go index 939a185..fb878b1 100644 --- a/module/feature/product/interface.go +++ b/module/feature/product/interface.go @@ -32,6 +32,8 @@ type RepositoryProductInterface interface { GetProductCountByCategoryName(categoryName string) (int64, error) GetProductBySearchAndFilter(page, perPage int, sortBy, search string) ([]*entities.ProductModels, int64, error) GetProductByFilter(page, perPage int, sortBy string) ([]*entities.ProductModels, int64, error) + GetRatedProductsInRange(page, perPage int, lowerBound, upperBound float64) ([]*entities.ProductModels, int64, error) + SearchByNameAndFilterByRating(page, perPage int, name, ratingParam string, lowerBound, upperBound float64) ([]*entities.ProductModels, int64, error) } type ServiceProductInterface interface { @@ -58,6 +60,8 @@ type ServiceProductInterface interface { GetProductsByCategoryName(categoryName string, page, perPage int) ([]*entities.ProductModels, int64, error) GetProductsBySearchAndFilter(page, perPage int, filter, search string) ([]*entities.ProductModels, int64, error) GetProductsByFilter(page, perPage int, filter string) ([]*entities.ProductModels, int64, error) + GetRatedProductsInRange(page, perPage int, ratingParam string) ([]*entities.ProductModels, int64, error) + SearchByNameAndFilterByRating(page, perPage int, name, ratingParam string) ([]*entities.ProductModels, int64, error) } type HandlerProductInterface interface { diff --git a/module/feature/product/repository/repository.go b/module/feature/product/repository/repository.go index c7d8008..50b86c6 100644 --- a/module/feature/product/repository/repository.go +++ b/module/feature/product/repository/repository.go @@ -2,11 +2,12 @@ package repository import ( "errors" + "strings" + "time" + "github.com/capstone-kelompok-7/backend-disappear/module/entities" "github.com/capstone-kelompok-7/backend-disappear/module/feature/product" "gorm.io/gorm" - "strings" - "time" ) type ProductRepository struct { @@ -419,3 +420,54 @@ func (r *ProductRepository) GetProductByFilter(page, perPage int, sortBy string) return products, totalItems, nil } + +func (r *ProductRepository) GetRatedProductsInRange(page, perPage int, lowerBound, upperBound float64) ([]*entities.ProductModels, int64, error) { + var products []*entities.ProductModels + offset := (page - 1) * perPage + + db := r.db.Model(&entities.ProductModels{}).Where("deleted_at IS NULL") + + err := db.Where("rating BETWEEN ? AND ?", lowerBound, upperBound). + Order("rating").Offset(offset).Limit(perPage).Find(&products).Error + if err != nil { + return nil, 0, err + } + + var totalItems int64 + if err := db.Count(&totalItems).Error; err != nil { + return nil, 0, err + } + + return products, totalItems, nil +} + +func (r *ProductRepository) SearchByNameAndFilterByRating(page, perPage int, name, ratingParam string, lowerBound, upperBound float64) ([]*entities.ProductModels, int64, error) { + var products []*entities.ProductModels + offset := (page - 1) * perPage + query := r.db.Model(&entities.ProductModels{}). + Offset(offset). + Limit(perPage). + Preload("Categories"). + Preload("ProductPhotos"). + Where("deleted_at IS NULL") + + if name != "" { + query = query.Where("name LIKE ?", "%"+name+"%") + } + + if ratingParam != "" { + query = query.Where("rating BETWEEN ? AND ?", lowerBound, upperBound) + } + + err := query.Find(&products).Error + if err != nil { + return nil, 0, err + } + + var totalItems int64 + if err := query.Count(&totalItems).Error; err != nil { + return nil, 0, err + } + + return products, totalItems, nil +} diff --git a/module/feature/product/service/service.go b/module/feature/product/service/service.go index aef6d93..a5d115f 100644 --- a/module/feature/product/service/service.go +++ b/module/feature/product/service/service.go @@ -3,6 +3,7 @@ package service import ( "errors" "math" + "strings" "time" "github.com/capstone-kelompok-7/backend-disappear/module/entities" @@ -369,3 +370,58 @@ func isValidFilter(filter string) bool { } return !validFilters[filter] } + +func getRatingBounds(ratingParam string) (float64, float64, error) { + ratingParam = strings.ToLower(ratingParam) + var lowerBound, upperBound float64 + + switch ratingParam { + case "sangat buruk": + lowerBound = 0.1 + upperBound = 1.9 + case "buruk": + lowerBound = 2 + upperBound = 2.9 + case "sedang": + lowerBound = 3 + upperBound = 3.9 + case "baik": + lowerBound = 4 + upperBound = 4.9 + case "sangat baik": + lowerBound = 5 + upperBound = 5.0 + default: + return 0, 0, errors.New("tipe filter tidak valid") + } + + return lowerBound, upperBound, nil +} + +func (s *ProductService) GetRatedProductsInRange(page, perPage int, ratingParam string) ([]*entities.ProductModels, int64, error) { + lowerBound, upperBound, err := getRatingBounds(ratingParam) + if err != nil { + return nil, 0, err + } + + products, totalItems, err := s.repo.GetRatedProductsInRange(page, perPage, lowerBound, upperBound) + if err != nil { + return nil, 0, err + } + + return products, totalItems, nil +} + +func (s *ProductService) SearchByNameAndFilterByRating(page, perPage int, name, ratingParam string) ([]*entities.ProductModels, int64, error) { + lowerBound, upperBound, err := getRatingBounds(ratingParam) + if err != nil { + return nil, 0, err + } + + products, totalItems, err := s.repo.SearchByNameAndFilterByRating(page, perPage, name, ratingParam, lowerBound, upperBound) + if err != nil { + return nil, 0, err + } + + return products, totalItems, nil +}