From 2d035074a48882edf2a7b3ed457d785329bbcaaa Mon Sep 17 00:00:00 2001 From: pahmiudahgede Date: Thu, 15 May 2025 09:11:49 +0700 Subject: [PATCH] fix: fixing and refact code statement and nil value --- dto/address_dto.go | 24 +-- dto/collector_dto.go | 31 +++- dto/requestpickup_dto.go | 17 +- dto/trash_dto.go | 10 +- dto/user_dto.go | 18 +- internal/handler/collector_handler.go | 34 ++++ internal/handler/requestpickup_handler.go | 48 +++--- internal/repositories/collector_repo.go | 58 ++++--- internal/repositories/requestpickup_repo.go | 59 ++++++- internal/services/address_service.go | 2 +- internal/services/collector_service.go | 115 +++++++++---- internal/services/requestpickup_service.go | 178 ++++++++++++++++++-- internal/services/trash_service.go | 2 + model/collector_model.go | 7 +- model/requestpickup_model.go | 19 ++- presentation/collector_route.go | 10 +- presentation/requestpickup_route.go | 12 +- presentation/trash_route.go | 19 ++- router/setup_routes.go.go | 4 +- 19 files changed, 506 insertions(+), 161 deletions(-) diff --git a/dto/address_dto.go b/dto/address_dto.go index b689ad5..b1bdcd6 100644 --- a/dto/address_dto.go +++ b/dto/address_dto.go @@ -3,18 +3,18 @@ package dto import "strings" type AddressResponseDTO struct { - UserID string `json:"user_id"` - ID string `json:"address_id"` - Province string `json:"province"` - Regency string `json:"regency"` - District string `json:"district"` - Village string `json:"village"` - PostalCode string `json:"postalCode"` - Detail string `json:"detail"` - Latitude float64 `json:"latitude"` - Longitude float64 `json:"longitude"` - CreatedAt string `json:"createdAt"` - UpdatedAt string `json:"updatedAt"` + UserID string `json:"user_id,omitempty"` + ID string `json:"address_id,omitempty"` + Province string `json:"province,omitempty"` + Regency string `json:"regency,omitempty"` + District string `json:"district,omitempty"` + Village string `json:"village,omitempty"` + PostalCode string `json:"postalCode,omitempty"` + Detail string `json:"detail,omitempty"` + Latitude float64 `json:"latitude,omitempty"` + Longitude float64 `json:"longitude,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` + UpdatedAt string `json:"updatedAt,omitempty"` } type CreateAddressDTO struct { diff --git a/dto/collector_dto.go b/dto/collector_dto.go index c1f96fb..21e89c5 100644 --- a/dto/collector_dto.go +++ b/dto/collector_dto.go @@ -7,14 +7,31 @@ type RequestCollectorDTO struct { AddressId string `json:"address_id"` } +type SelectCollectorRequest struct { + Collector_id string `json:"collector_id"` +} + +func (r *SelectCollectorRequest) ValidateSelectCollectorRequest() (map[string][]string, bool) { + errors := make(map[string][]string) + + if strings.TrimSpace(r.Collector_id) == "" { + errors["collector_id"] = append(errors["collector_id"], "collector_id harus diisi") + } + if len(errors) > 0 { + return errors, false + } + + return nil, true +} + type ResponseCollectorDTO struct { - ID string `json:"collector_id"` - UserId string `json:"user_id"` - AddressId string `json:"address_id"` - JobStatus string `json:"job_status"` - Rating float32 `json:"rating"` - // CreatedAt string `json:"createdAt"` - // UpdatedAt string `json:"updatedAt"` + ID string `json:"collector_id"` + UserId string `json:"user_id"` + User []UserResponseDTO `json:"user,omitempty"` + AddressId string `json:"address_id"` + Address []AddressResponseDTO `json:"address,omitempty"` + JobStatus *string `json:"job_status,omitempty"` + Rating float32 `json:"rating"` } func (r *RequestCollectorDTO) ValidateRequestColector() (map[string][]string, bool) { diff --git a/dto/requestpickup_dto.go b/dto/requestpickup_dto.go index 643f95c..01e7ad7 100644 --- a/dto/requestpickup_dto.go +++ b/dto/requestpickup_dto.go @@ -6,10 +6,11 @@ import ( ) type RequestPickup struct { - RequestItems []RequestPickupItem `json:"request_items"` - EvidenceImage string `json:"evidence_image"` AddressID string `json:"address_id"` RequestMethod string `json:"request_method"` + EvidenceImage string `json:"evidence_image"` + Notes string `json:"notes"` + RequestItems []RequestPickupItem `json:"request_items"` } type RequestPickupItem struct { @@ -20,10 +21,14 @@ type RequestPickupItem struct { type ResponseRequestPickup struct { ID string `json:"id,omitempty"` UserId string `json:"user_id,omitempty"` + User []UserResponseDTO `json:"user,omitempty"` AddressID string `json:"address_id,omitempty"` + Address []AddressResponseDTO `json:"address,omitempty"` EvidenceImage string `json:"evidence_image,omitempty"` + Notes string `json:"notes,omitempty"` StatusPickup string `json:"status_pickup,omitempty"` CollectorID string `json:"collectorid,omitempty"` + Collector []ResponseCollectorDTO `json:"collector,omitempty"` ConfirmedByCollectorAt string `json:"confirmedat,omitempty"` CreatedAt string `json:"created_at,omitempty"` UpdatedAt string `json:"updated_at,omitempty"` @@ -31,10 +36,10 @@ type ResponseRequestPickup struct { } type ResponseRequestPickupItem struct { - ID string `json:"id"` - // TrashCategoryID string `json:"trash_category_id"` - TrashCategoryName string `json:"trash_category_name"` - EstimatedAmount float64 `json:"estimated_amount"` + ID string `json:"id,omitempty"` + TrashCategoryID string `json:"trash_category_id,omitempty"` + TrashCategory []ResponseTrashCategoryDTO `json:"trash_category,omitempty"` + EstimatedAmount float64 `json:"estimated_amount,omitempty"` } func (r *RequestPickup) ValidateRequestPickup() (map[string][]string, bool) { diff --git a/dto/trash_dto.go b/dto/trash_dto.go index 9df527f..092386d 100644 --- a/dto/trash_dto.go +++ b/dto/trash_dto.go @@ -8,11 +8,11 @@ type RequestTrashCategoryDTO struct { } type ResponseTrashCategoryDTO struct { - ID string `json:"id"` - Name string `json:"name"` - Icon string `json:"icon"` - CreatedAt string `json:"createdAt"` - UpdatedAt string `json:"updatedAt"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Icon string `json:"icon,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` + UpdatedAt string `json:"updatedAt,omitempty"` Details []ResponseTrashDetailDTO `json:"details,omitempty"` } diff --git a/dto/user_dto.go b/dto/user_dto.go index 9558bd6..3a1164c 100644 --- a/dto/user_dto.go +++ b/dto/user_dto.go @@ -6,16 +6,16 @@ import ( ) type UserResponseDTO struct { - ID string `json:"id"` - Username string `json:"username"` + ID string `json:"id,omitempty"` + Username string `json:"username,omitempty"` Avatar *string `json:"photoprofile,omitempty"` - Name string `json:"name"` - Phone string `json:"phone"` - Email string `json:"email"` - EmailVerified bool `json:"emailVerified"` - RoleName string `json:"role"` - CreatedAt string `json:"createdAt"` - UpdatedAt string `json:"updatedAt"` + Name string `json:"name,omitempty"` + Phone string `json:"phone,omitempty"` + Email string `json:"email,omitempty"` + EmailVerified bool `json:"emailVerified,omitempty"` + RoleName string `json:"role,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` + UpdatedAt string `json:"updatedAt,omitempty"` } type RequestUserDTO struct { diff --git a/internal/handler/collector_handler.go b/internal/handler/collector_handler.go index cb2d738..355c8be 100644 --- a/internal/handler/collector_handler.go +++ b/internal/handler/collector_handler.go @@ -1,6 +1,8 @@ package handler import ( + "fmt" + "rijig/dto" "rijig/internal/services" "rijig/utils" @@ -34,3 +36,35 @@ func (h *CollectorHandler) ConfirmRequestPickup(c *fiber.Ctx) error { return utils.SuccessResponse(c, req, "Request pickup confirmed successfully") } + +func (h *CollectorHandler) GetAvaibleCollector(c *fiber.Ctx) error { + + userId := c.Locals("userID").(string) + + requests, err := h.service.FindCollectorsNearby(userId) + if err != nil { + return utils.ErrorResponse(c, err.Error()) + } + + return utils.SuccessResponse(c, requests, "menampilkan data collector terdekat") +} + +func (h *CollectorHandler) ConfirmRequestManualPickup(c *fiber.Ctx) error { + userId := c.Locals("userID").(string) + requestId := c.Params("request_id") + if requestId == "" { + fmt.Println("requestid dibutuhkan") + } + + var request dto.SelectCollectorRequest + if err := c.BodyParser(&request); err != nil { + return fmt.Errorf("error parsing request body: %v", err) + } + + message, err := h.service.ConfirmRequestManualPickup(requestId, userId) + if err != nil { + return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Error confirming pickup: %v", err)) + } + + return utils.SuccessResponse(c, message, "berhasil konfirmasi request") +} diff --git a/internal/handler/requestpickup_handler.go b/internal/handler/requestpickup_handler.go index 7558093..0984cd2 100644 --- a/internal/handler/requestpickup_handler.go +++ b/internal/handler/requestpickup_handler.go @@ -53,32 +53,40 @@ func (h *RequestPickupHandler) GetRequestPickupByID(c *fiber.Ctx) error { return utils.SuccessResponse(c, response, "Request pickup retrieved successfully") } -// func (h *RequestPickupHandler) GetAutomaticRequestByUser(c *fiber.Ctx) error { - -// collectorId, ok := c.Locals("userID").(string) -// if !ok || collectorId == "" { -// return utils.ErrorResponse(c, "Unauthorized: User session not found") -// } - -// requestPickups, err := h.service.GetAllAutomaticRequestPickup(collectorId) -// if err != nil { - -// return utils.ErrorResponse(c, err.Error()) -// } - -// return utils.SuccessResponse(c, requestPickups, "Request pickups fetched successfully") -// } - func (h *RequestPickupHandler) GetRequestPickups(c *fiber.Ctx) error { - // Get userID from Locals + collectorId := c.Locals("userID").(string) - // Call service layer to get the request pickups requests, err := h.service.GetRequestPickupsForCollector(collectorId) if err != nil { return utils.ErrorResponse(c, err.Error()) } - // Return response return utils.SuccessResponse(c, requests, "Automatic request pickups retrieved successfully") -} \ No newline at end of file +} + +func (h *RequestPickupHandler) AssignCollectorToRequest(c *fiber.Ctx) error { + userId, ok := c.Locals("userID").(string) + if !ok || userId == "" { + return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found") + } + + var request dto.SelectCollectorRequest + errors, valid := request.ValidateSelectCollectorRequest() + if !valid { + return utils.ValidationErrorResponse(c, errors) + } + + if err := c.BodyParser(&request); err != nil { + return fmt.Errorf("error parsing request body: %v", err) + } + + err := h.service.SelectCollectorInRequest(userId, request.Collector_id) + if err != nil { + + return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Error assigning collector: %v", err)) + } + + return utils.GenericResponse(c, fiber.StatusOK, "berhasil memilih collector") +} + diff --git a/internal/repositories/collector_repo.go b/internal/repositories/collector_repo.go index 0062610..5f0ef53 100644 --- a/internal/repositories/collector_repo.go +++ b/internal/repositories/collector_repo.go @@ -5,7 +5,6 @@ import ( "fmt" "log" "rijig/model" - "rijig/utils" "gorm.io/gorm" ) @@ -13,9 +12,10 @@ import ( type CollectorRepository interface { FindActiveCollectors() ([]model.Collector, error) FindCollectorById(collector_id string) (*model.Collector, error) + FindCollectorByIdWithoutAddr(collector_id string) (*model.Collector, error) CreateCollector(collector *model.Collector) error UpdateCollector(userId string, jobStatus string) (*model.Collector, error) - FindAllAutomaticMethodRequestWithDistance(requestMethod, statuspickup string, collectorLat, collectorLon float64, maxDistance float64) ([]model.RequestPickup, error) + // FindAllAutomaticMethodRequestWithDistance(requestMethod, statuspickup string, collectorLat, collectorLon float64, maxDistance float64) ([]model.RequestPickup, error) } type collectorRepository struct { @@ -29,7 +29,7 @@ func NewCollectorRepository(db *gorm.DB) CollectorRepository { func (r *collectorRepository) FindActiveCollectors() ([]model.Collector, error) { var collectors []model.Collector - err := r.DB.Where("job_status = ?", "active").First(&collectors).Error + err := r.DB.Preload("Address").Where("job_status = ?", "active").First(&collectors).Error if err != nil { return nil, fmt.Errorf("failed to fetch active collectors: %v", err) } @@ -38,6 +38,16 @@ func (r *collectorRepository) FindActiveCollectors() ([]model.Collector, error) } func (r *collectorRepository) FindCollectorById(collector_id string) (*model.Collector, error) { + var collector model.Collector + err := r.DB.Preload("Address").Where("user_id = ?", collector_id).First(&collector).Error + if err != nil { + return nil, fmt.Errorf("error fetching collector: %v", err) + } + fmt.Printf("menampilkan data collector %v", &collector) + return &collector, nil +} + +func (r *collectorRepository) FindCollectorByIdWithoutAddr(collector_id string) (*model.Collector, error) { var collector model.Collector err := r.DB.Where("user_id = ?", collector_id).First(&collector).Error if err != nil { @@ -77,29 +87,29 @@ func (r *collectorRepository) UpdateCollector(userId string, jobStatus string) ( return &existingCollector, nil } -// #====experimen====# -func (r *collectorRepository) FindAllAutomaticMethodRequestWithDistance(requestMethod, statuspickup string, collectorLat, collectorLon float64, maxDistance float64) ([]model.RequestPickup, error) { - var requests []model.RequestPickup +// // #====experimen====# +// func (r *collectorRepository) FindAllAutomaticMethodRequestWithDistance(requestMethod, statuspickup string, collectorLat, collectorLon float64, maxDistance float64) ([]model.RequestPickup, error) { +// var requests []model.RequestPickup - err := r.DB.Preload("RequestItems"). - Where("request_method = ? AND status_pickup = ?", requestMethod, statuspickup). - Find(&requests).Error - if err != nil { - return nil, fmt.Errorf("error fetching request pickups with request_method '%s' and status '%s': %v", requestMethod, statuspickup, err) - } +// err := r.DB.Preload("RequestItems"). +// Where("request_method = ? AND status_pickup = ?", requestMethod, statuspickup). +// Find(&requests).Error +// if err != nil { +// return nil, fmt.Errorf("error fetching request pickups with request_method '%s' and status '%s': %v", requestMethod, statuspickup, err) +// } - var nearbyRequests []model.RequestPickup - for _, request := range requests { - address := request.Address +// var nearbyRequests []model.RequestPickup +// for _, request := range requests { +// address := request.Address - requestCoord := utils.Coord{Lat: address.Latitude, Lon: address.Longitude} - collectorCoord := utils.Coord{Lat: collectorLat, Lon: collectorLon} - _, km := utils.Distance(requestCoord, collectorCoord) +// requestCoord := utils.Coord{Lat: address.Latitude, Lon: address.Longitude} +// collectorCoord := utils.Coord{Lat: collectorLat, Lon: collectorLon} +// _, km := utils.Distance(requestCoord, collectorCoord) - if km <= maxDistance { - nearbyRequests = append(nearbyRequests, request) - } - } +// if km <= maxDistance { +// nearbyRequests = append(nearbyRequests, request) +// } +// } - return nearbyRequests, nil -} +// return nearbyRequests, nil +// } diff --git a/internal/repositories/requestpickup_repo.go b/internal/repositories/requestpickup_repo.go index 0eadea7..76fd64e 100644 --- a/internal/repositories/requestpickup_repo.go +++ b/internal/repositories/requestpickup_repo.go @@ -13,9 +13,12 @@ type RequestPickupRepository interface { FindRequestPickupByID(id string) (*model.RequestPickup, error) FindAllRequestPickups(userId string) ([]model.RequestPickup, error) FindAllAutomaticMethodRequest(requestMethod, statuspickup string) ([]model.RequestPickup, error) - FindRequestPickupByAddressAndStatus(userId, status string) (*model.RequestPickup, error) + FindRequestPickupByAddressAndStatus(userId, status, method string) (*model.RequestPickup, error) + FindRequestPickupByStatus(userId, status, method string) (*model.RequestPickup, error) GetRequestPickupItems(requestPickupId string) ([]model.RequestPickupItem, error) - GetAutomaticRequestPickupsForCollector(collectorId string) ([]model.RequestPickup, error) + GetAutomaticRequestPickupsForCollector() ([]model.RequestPickup, error) + GetManualReqMethodforCollect(collector_id string) ([]model.RequestPickup, error) + // SelectCollectorInRequest(userId string, collectorId string) error UpdateRequestPickup(id string, request *model.RequestPickup) error DeleteRequestPickup(id string) error } @@ -78,9 +81,21 @@ func (r *requestPickupRepository) FindAllAutomaticMethodRequest(requestMethod, s return requests, nil } -func (r *requestPickupRepository) FindRequestPickupByAddressAndStatus(userId, status string) (*model.RequestPickup, error) { +func (r *requestPickupRepository) FindRequestPickupByAddressAndStatus(userId, status, method string) (*model.RequestPickup, error) { var request model.RequestPickup - err := r.DB.Where("user_id = ? AND status_pickup = ?", userId, status).First(&request).Error + err := r.DB.Preload("Address").Where("user_id = ? AND status_pickup = ? AND request_method =?", userId, status, method).First(&request).Error + if err != nil { + if err == gorm.ErrRecordNotFound { + return nil, nil + } + return nil, fmt.Errorf("failed to check existing request pickup: %v", err) + } + return &request, nil +} + +func (r *requestPickupRepository) FindRequestPickupByStatus(userId, status, method string) (*model.RequestPickup, error) { + var request model.RequestPickup + err := r.DB.Where("user_id = ? AND status_pickup = ? AND request_method =?", userId, status, method).First(&request).Error if err != nil { if err == gorm.ErrRecordNotFound { return nil, nil @@ -99,6 +114,28 @@ func (r *requestPickupRepository) UpdateRequestPickup(id string, request *model. return nil } +// func (r *requestPickupRepository) SelectCollectorInRequest(userId string, collectorId string) error { +// var request model.RequestPickup +// err := r.DB.Model(&model.RequestPickup{}). +// Where("user_id = ? AND status_pickup = ? AND request_method = ? AND collector_id IS NULL", userId, "waiting_collector", "manual"). +// First(&request).Error +// if err != nil { +// if err == gorm.ErrRecordNotFound { +// return fmt.Errorf("no matching request pickup found for user %s", userId) +// } +// return fmt.Errorf("failed to find request pickup: %v", err) +// } + +// err = r.DB.Model(&model.RequestPickup{}). +// Where("id = ?", request.ID). +// Update("collector_id", collectorId). +// Error +// if err != nil { +// return fmt.Errorf("failed to update collector_id: %v", err) +// } +// return nil +// } + func (r *requestPickupRepository) DeleteRequestPickup(id string) error { if err := r.DB.Where("request_pickup_id = ?", id).Delete(&model.RequestPickupItem{}).Error; err != nil { @@ -112,16 +149,24 @@ func (r *requestPickupRepository) DeleteRequestPickup(id string) error { return nil } -func (r *requestPickupRepository) GetAutomaticRequestPickupsForCollector(collectorId string) ([]model.RequestPickup, error) { +func (r *requestPickupRepository) GetAutomaticRequestPickupsForCollector() ([]model.RequestPickup, error) { var requests []model.RequestPickup - err := r.DB.Preload("Address"). - Where("request_method = ? AND status_pickup = ?", "otomatis", "waiting_collector"). + Where("request_method = ? AND status_pickup = ? AND collector_id = ?", "otomatis", "waiting_collector", nil). Find(&requests).Error if err != nil { return nil, fmt.Errorf("error fetching pickup requests: %v", err) } + return requests, nil +} +func (r *requestPickupRepository) GetManualReqMethodforCollect(collector_id string) ([]model.RequestPickup, error) { + var requests []model.RequestPickup + err := r.DB.Where("request_method = ? AND status_pickup = ? AND collector_id = ?", "otomatis", "waiting_collector", collector_id). + Find(&requests).Error + if err != nil { + return nil, fmt.Errorf("error fetching pickup requests: %v", err) + } return requests, nil } diff --git a/internal/services/address_service.go b/internal/services/address_service.go index 899f699..b6b25c8 100644 --- a/internal/services/address_service.go +++ b/internal/services/address_service.go @@ -304,7 +304,7 @@ func (s *addressService) UpdateAddress(userID, id string, addressDTO dto.CreateA address.Detail = addressDTO.Detail address.Latitude = addressDTO.Latitude address.Longitude = addressDTO.Longitude - address.UpdatedAt = time.Now() + // address.UpdatedAt = time.Now() err = s.AddressRepo.UpdateAddress(address) if err != nil { diff --git a/internal/services/collector_service.go b/internal/services/collector_service.go index 5cc255f..9cf745e 100644 --- a/internal/services/collector_service.go +++ b/internal/services/collector_service.go @@ -5,23 +5,27 @@ import ( "rijig/dto" "rijig/internal/repositories" "rijig/utils" + "time" ) type CollectorService interface { FindCollectorsNearby(userId string) ([]dto.ResponseCollectorDTO, error) ConfirmRequestPickup(requestId, collectorId string) (*dto.ResponseRequestPickup, error) + ConfirmRequestManualPickup(requestId, collectorId string) (any, error) } type collectorService struct { repo repositories.CollectorRepository - repoReq repositories.RequestPickupRepository + repoColl repositories.RequestPickupRepository repoAddress repositories.AddressRepository + repoUser repositories.UserProfilRepository } func NewCollectorService(repo repositories.CollectorRepository, - repoReq repositories.RequestPickupRepository, - repoAddress repositories.AddressRepository) CollectorService { - return &collectorService{repo: repo, repoReq: repoReq, repoAddress: repoAddress} + repoColl repositories.RequestPickupRepository, + repoAddress repositories.AddressRepository, + repoUser repositories.UserProfilRepository) CollectorService { + return &collectorService{repo: repo, repoColl: repoColl, repoAddress: repoAddress, repoUser: repoUser} } func (s *collectorService) FindCollectorsNearby(userId string) ([]dto.ResponseCollectorDTO, error) { @@ -30,51 +34,62 @@ func (s *collectorService) FindCollectorsNearby(userId string) ([]dto.ResponseCo return nil, fmt.Errorf("error fetching active collectors: %v", err) } - request, err := s.repoReq.FindRequestPickupByAddressAndStatus(userId, "waiting_collector") - if err != nil { - return nil, fmt.Errorf("gagal mendapatkan data request pickup dengan userid: %v", err) - } - - reqpickaddress, err := s.repoAddress.FindAddressByID(request.AddressId) - if err != nil { - return nil, fmt.Errorf("error fetching address for request pickup %s: %v", request.ID, err) - } - - var nearbyCollectorsResponse []dto.ResponseCollectorDTO - var maxDistance = 10.0 + var avaibleCollectResp []dto.ResponseCollectorDTO for _, collector := range collectors { - address, err := s.repoAddress.FindAddressByID(collector.AddressId) + request, err := s.repoColl.FindRequestPickupByAddressAndStatus(userId, "waiting_collector", "otomatis") if err != nil { - return nil, fmt.Errorf("error fetching address for collector %s: %v", collector.ID, err) + return nil, fmt.Errorf("gagal mendapatkan data request pickup dengan userid: %v", err) } - collectorCoord := utils.Coord{Lat: reqpickaddress.Latitude, Lon: reqpickaddress.Longitude} - userCoord := utils.Coord{Lat: address.Latitude, Lon: address.Longitude} + _, distance := utils.Distance( + utils.Coord{Lat: request.Address.Latitude, Lon: request.Address.Longitude}, + utils.Coord{Lat: collector.Address.Latitude, Lon: collector.Address.Longitude}, + ) - _, km := utils.Distance(collectorCoord, userCoord) + if distance <= 20 { - if km <= maxDistance { - - nearbyCollectorsResponse = append(nearbyCollectorsResponse, dto.ResponseCollectorDTO{ + mappedRequest := dto.ResponseCollectorDTO{ ID: collector.ID, - AddressId: collector.User.Name, - Rating: collector.Rating, - }) + UserId: collector.UserID, + AddressId: collector.AddressId, + + Rating: collector.Rating, + } + + user, err := s.repoUser.FindByID(collector.UserID) + if err != nil { + return nil, fmt.Errorf("error fetching user data: %v", err) + } + mappedRequest.User = []dto.UserResponseDTO{ + { + Name: user.Name, + Phone: user.Phone, + }, + } + + address, err := s.repoAddress.FindAddressByID(collector.AddressId) + if err != nil { + return nil, fmt.Errorf("error fetching address data: %v", err) + } + mappedRequest.Address = []dto.AddressResponseDTO{ + { + District: address.District, + Village: address.Village, + Detail: address.Detail, + }, + } + + avaibleCollectResp = append(avaibleCollectResp, mappedRequest) } } - if len(nearbyCollectorsResponse) == 0 { - return nil, fmt.Errorf("no request pickups found within %v km", maxDistance) - } - - return nearbyCollectorsResponse, nil + return avaibleCollectResp, nil } func (s *collectorService) ConfirmRequestPickup(requestId, collectorId string) (*dto.ResponseRequestPickup, error) { - - request, err := s.repoReq.FindRequestPickupByID(requestId) + request, err := s.repoColl.FindRequestPickupByID(requestId) if err != nil { return nil, fmt.Errorf("request pickup not found: %v", err) } @@ -90,13 +105,14 @@ func (s *collectorService) ConfirmRequestPickup(requestId, collectorId string) ( request.StatusPickup = "confirmed" request.CollectorID = &collector.ID + *request.ConfirmedByCollectorAt = time.Now() - err = s.repoReq.UpdateRequestPickup(requestId, request) + err = s.repoColl.UpdateRequestPickup(requestId, request) if err != nil { return nil, fmt.Errorf("failed to update request pickup: %v", err) } - confirmedAt, _ := utils.FormatDateToIndonesianFormat(request.ConfirmedByCollectorAt) + confirmedAt, _ := utils.FormatDateToIndonesianFormat(*request.ConfirmedByCollectorAt) response := dto.ResponseRequestPickup{ StatusPickup: request.StatusPickup, @@ -106,3 +122,30 @@ func (s *collectorService) ConfirmRequestPickup(requestId, collectorId string) ( return &response, nil } + +func (s *collectorService) ConfirmRequestManualPickup(requestId, collectorId string) (any, error) { + + request, err := s.repoColl.FindRequestPickupByID(requestId) + if err != nil { + return nil, fmt.Errorf("collector tidak ditemukan: %v", err) + } + + coll, err := s.repo.FindCollectorByIdWithoutAddr(collectorId) + if err != nil { + return nil, fmt.Errorf("%v", err) + } + + if coll.ID != *request.CollectorID { + return nil, fmt.Errorf("collectorid tidak sesuai dengan request") + } + + request.StatusPickup = "confirmed" + *request.ConfirmedByCollectorAt = time.Now() + + err = s.repoColl.UpdateRequestPickup(requestId, request) + if err != nil { + return nil, fmt.Errorf("failed to update request pickup: %v", err) + } + + return "berhasil konfirmasi request pickup", nil +} \ No newline at end of file diff --git a/internal/services/requestpickup_service.go b/internal/services/requestpickup_service.go index ecd4514..f79996d 100644 --- a/internal/services/requestpickup_service.go +++ b/internal/services/requestpickup_service.go @@ -12,23 +12,24 @@ type RequestPickupService interface { CreateRequestPickup(request dto.RequestPickup, UserId string) (*dto.ResponseRequestPickup, error) GetRequestPickupByID(id string) (*dto.ResponseRequestPickup, error) GetAllRequestPickups(userid string) ([]dto.ResponseRequestPickup, error) - // GetAllAutomaticRequestPickups(collector_id string) ([]dto.ResponseRequestPickup, error) - // GetAllAutomaticRequestPickup(collectorId string) ([]dto.ResponseRequestPickup, error) - GetRequestPickupsForCollector(collectorId string) ([]dto.ResponseRequestPickup, error) + SelectCollectorInRequest(userId, collectorId string) error } type requestPickupService struct { repo repositories.RequestPickupRepository - repoReq repositories.CollectorRepository + repoColl repositories.CollectorRepository repoAddress repositories.AddressRepository repoTrash repositories.TrashRepository + repoUser repositories.UserProfilRepository } func NewRequestPickupService(repo repositories.RequestPickupRepository, + repoColl repositories.CollectorRepository, repoAddress repositories.AddressRepository, - repoTrash repositories.TrashRepository) RequestPickupService { - return &requestPickupService{repo: repo, repoAddress: repoAddress, repoTrash: repoTrash} + repoTrash repositories.TrashRepository, + repoUser repositories.UserProfilRepository) RequestPickupService { + return &requestPickupService{repo: repo, repoColl: repoColl, repoAddress: repoAddress, repoTrash: repoTrash, repoUser: repoUser} } func (s *requestPickupService) CreateRequestPickup(request dto.RequestPickup, UserId string) (*dto.ResponseRequestPickup, error) { @@ -43,7 +44,7 @@ func (s *requestPickupService) CreateRequestPickup(request dto.RequestPickup, Us return nil, fmt.Errorf("address with ID %s not found", request.AddressID) } - existingRequest, err := s.repo.FindRequestPickupByAddressAndStatus(UserId, "waiting_collector") + existingRequest, err := s.repo.FindRequestPickupByAddressAndStatus(UserId, "waiting_collector", "otomatis") if err != nil { return nil, fmt.Errorf("error checking for existing request pickup: %v", err) } @@ -94,9 +95,9 @@ func (s *requestPickupService) CreateRequestPickup(request dto.RequestPickup, Us } response.RequestItems = append(response.RequestItems, dto.ResponseRequestPickupItem{ - ID: modelItem.ID, - TrashCategoryName: findTrashCategory.Name, - EstimatedAmount: modelItem.EstimatedAmount, + ID: modelItem.ID, + TrashCategory: []dto.ResponseTrashCategoryDTO{{Name: findTrashCategory.Name, Icon: findTrashCategory.Icon}}, + EstimatedAmount: modelItem.EstimatedAmount, }) } @@ -152,8 +153,7 @@ func (s *requestPickupService) GetAllRequestPickups(userid string) ([]dto.Respon } func (s *requestPickupService) GetRequestPickupsForCollector(collectorId string) ([]dto.ResponseRequestPickup, error) { - - requests, err := s.repo.GetAutomaticRequestPickupsForCollector(collectorId) + requests, err := s.repo.GetAutomaticRequestPickupsForCollector() if err != nil { return nil, fmt.Errorf("error retrieving automatic pickup requests: %v", err) } @@ -162,8 +162,13 @@ func (s *requestPickupService) GetRequestPickupsForCollector(collectorId string) for _, req := range requests { + collector, err := s.repoColl.FindCollectorById(collectorId) + if err != nil { + return nil, fmt.Errorf("error fetching collector data: %v", err) + } + _, distance := utils.Distance( - utils.Coord{Lat: req.Address.Latitude, Lon: req.Address.Longitude}, + utils.Coord{Lat: collector.Address.Latitude, Lon: collector.Address.Longitude}, utils.Coord{Lat: req.Address.Latitude, Lon: req.Address.Longitude}, ) @@ -179,17 +184,49 @@ func (s *requestPickupService) GetRequestPickupsForCollector(collectorId string) UpdatedAt: req.UpdatedAt.Format("2006-01-02 15:04:05"), } + user, err := s.repoUser.FindByID(req.UserId) + if err != nil { + return nil, fmt.Errorf("error fetching user data: %v", err) + } + mappedRequest.User = []dto.UserResponseDTO{ + { + Name: user.Name, + Phone: user.Phone, + }, + } + + address, err := s.repoAddress.FindAddressByID(req.AddressId) + if err != nil { + return nil, fmt.Errorf("error fetching address data: %v", err) + } + mappedRequest.Address = []dto.AddressResponseDTO{ + { + District: address.District, + Village: address.Village, + Detail: address.Detail, + }, + } + requestItems, err := s.repo.GetRequestPickupItems(req.ID) if err != nil { return nil, fmt.Errorf("error fetching request items: %v", err) } var mappedRequestItems []dto.ResponseRequestPickupItem + for _, item := range requestItems { + trashCategory, err := s.repoTrash.GetCategoryByID(item.TrashCategoryId) + if err != nil { + return nil, fmt.Errorf("error fetching trash category: %v", err) + } + mappedRequestItems = append(mappedRequestItems, dto.ResponseRequestPickupItem{ - ID: item.ID, - TrashCategoryName: item.TrashCategory.Name, - EstimatedAmount: item.EstimatedAmount, + ID: item.ID, + TrashCategory: []dto.ResponseTrashCategoryDTO{{ + Name: trashCategory.Name, + Icon: trashCategory.Icon, + }}, + EstimatedAmount: item.EstimatedAmount, }) } @@ -201,3 +238,112 @@ func (s *requestPickupService) GetRequestPickupsForCollector(collectorId string) return response, nil } + +func (s *requestPickupService) GetManualRequestPickupsForCollector(collectorId string) ([]dto.ResponseRequestPickup, error) { + + collector, err := s.repoColl.FindCollectorById(collectorId) + if err != nil { + return nil, fmt.Errorf("error fetching collector data: %v", err) + } + requests, err := s.repo.GetManualReqMethodforCollect(collector.ID) + if err != nil { + return nil, fmt.Errorf("error retrieving manual pickup requests: %v", err) + } + + var response []dto.ResponseRequestPickup + + for _, req := range requests { + + createdAt, _ := utils.FormatDateToIndonesianFormat(req.CreatedAt) + updatedAt, _ := utils.FormatDateToIndonesianFormat(req.UpdatedAt) + + mappedRequest := dto.ResponseRequestPickup{ + ID: req.ID, + UserId: req.UserId, + AddressID: req.AddressId, + EvidenceImage: req.EvidenceImage, + StatusPickup: req.StatusPickup, + CreatedAt: createdAt, + UpdatedAt: updatedAt, + } + + user, err := s.repoUser.FindByID(req.UserId) + if err != nil { + return nil, fmt.Errorf("error fetching user data: %v", err) + } + mappedRequest.User = []dto.UserResponseDTO{ + { + Name: user.Name, + Phone: user.Phone, + }, + } + + address, err := s.repoAddress.FindAddressByID(req.AddressId) + if err != nil { + return nil, fmt.Errorf("error fetching address data: %v", err) + } + mappedRequest.Address = []dto.AddressResponseDTO{ + { + District: address.District, + Village: address.Village, + Detail: address.Detail, + }, + } + + requestItems, err := s.repo.GetRequestPickupItems(req.ID) + if err != nil { + return nil, fmt.Errorf("error fetching request items: %v", err) + } + + var mappedRequestItems []dto.ResponseRequestPickupItem + + for _, item := range requestItems { + + trashCategory, err := s.repoTrash.GetCategoryByID(item.TrashCategoryId) + if err != nil { + return nil, fmt.Errorf("error fetching trash category: %v", err) + } + + mappedRequestItems = append(mappedRequestItems, dto.ResponseRequestPickupItem{ + ID: item.ID, + TrashCategory: []dto.ResponseTrashCategoryDTO{{ + Name: trashCategory.Name, + Icon: trashCategory.Icon, + }}, + EstimatedAmount: item.EstimatedAmount, + }) + } + + mappedRequest.RequestItems = mappedRequestItems + + response = append(response, mappedRequest) + } + + return response, nil +} + +func (s *requestPickupService) SelectCollectorInRequest(userId, collectorId string) error { + + request, err := s.repo.FindRequestPickupByStatus(userId, "waiting_collector", "manual") + if err != nil { + return fmt.Errorf("request pickup not found: %v", err) + } + + if request.StatusPickup != "waiting_collector" && request.RequestMethod != "manual" { + return fmt.Errorf("pickup request is not in 'waiting_collector' status and not 'manual' method") + } + + collector, err := s.repoColl.FindCollectorByIdWithoutAddr(collectorId) + if err != nil { + return fmt.Errorf("collector tidak ditemukan: %v", err) + } + + request.CollectorID = &collector.ID + + err = s.repo.UpdateRequestPickup(request.ID, request) + if err != nil { + return fmt.Errorf("failed to update request pickup: %v", err) + } + + return nil +} diff --git a/internal/services/trash_service.go b/internal/services/trash_service.go index cd66add..bb1cc29 100644 --- a/internal/services/trash_service.go +++ b/internal/services/trash_service.go @@ -244,6 +244,7 @@ func (s *trashService) GetCategories() ([]dto.ResponseTrashCategoryDTO, error) { var categoriesDTO []dto.ResponseTrashCategoryDTO for _, category := range categories { + // path := os.Getenv("BASE_URL") createdAt, _ := utils.FormatDateToIndonesianFormat(category.CreatedAt) updatedAt, _ := utils.FormatDateToIndonesianFormat(category.UpdatedAt) categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{ @@ -255,6 +256,7 @@ func (s *trashService) GetCategories() ([]dto.ResponseTrashCategoryDTO, error) { }) } + cacheData := map[string]interface{}{ "data": categoriesDTO, } diff --git a/model/collector_model.go b/model/collector_model.go index ed024f2..009ed98 100644 --- a/model/collector_model.go +++ b/model/collector_model.go @@ -4,8 +4,13 @@ type Collector struct { ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"` UserID string `gorm:"not null" json:"userId"` User User `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"user"` - JobStatus string `gorm:"default:nonactive" json:"jobstatus"` + JobStatus string `gorm:"default:inactive" json:"jobstatus"` Rating float32 `gorm:"default:5" json:"rating"` AddressId string `gorm:"not null" json:"address_id"` Address Address `gorm:"foreignKey:AddressId;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"address"` } + +// job_status { +// "active", +// "inactive" +// } diff --git a/model/requestpickup_model.go b/model/requestpickup_model.go index a8ee3e8..13402ca 100644 --- a/model/requestpickup_model.go +++ b/model/requestpickup_model.go @@ -12,9 +12,11 @@ type RequestPickup struct { Address Address `gorm:"foreignKey:AddressId;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"address"` RequestItems []RequestPickupItem `gorm:"foreignKey:RequestPickupId;constraint:OnDelete:CASCADE;" json:"request_items"` EvidenceImage string `json:"evidence_image"` + Notes string `json:"notes"` StatusPickup string `gorm:"default:'waiting_collector'" json:"status_pickup"` CollectorID *string `gorm:"type:uuid" json:"collector_id,omitempty"` - ConfirmedByCollectorAt time.Time `gorm:"default:current_timestamp" json:"confirmed_by_collector_at,omitempty"` + Collector Collector `gorm:"foreignKey:CollectorID;constraint:OnDelete:CASCADE;" json:"collector"` + ConfirmedByCollectorAt *time.Time `json:"confirmed_by_collector_at,omitempty"` RequestMethod string `gorm:"not null" json:"request_method"` CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"` UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"` @@ -25,6 +27,19 @@ type RequestPickupItem struct { RequestPickupId string `gorm:"not null" json:"request_pickup_id"` RequestPickup RequestPickup `gorm:"foreignKey:RequestPickupId;constraint:OnDelete:CASCADE;"` TrashCategoryId string `gorm:"not null" json:"trash_category_id"` - TrashCategory TrashCategory `gorm:"foreignKey:TrashCategoryId;constraint:OnDelete:CASCADE;"` + TrashCategory TrashCategory `gorm:"foreignKey:TrashCategoryId;constraint:OnDelete:CASCADE;" json:"trash_category"` EstimatedAmount float64 `gorm:"not null" json:"estimated_amount"` } + +// request_method { +// "otomatis", +// "manual" +// } + +// status_pickup { +// "waiting_collector", +// "confirmed", +// "collector_picking", +// "completed" +// "canceled" +// } diff --git a/presentation/collector_route.go b/presentation/collector_route.go index 451b3bc..93692b9 100644 --- a/presentation/collector_route.go +++ b/presentation/collector_route.go @@ -6,7 +6,8 @@ import ( "rijig/internal/repositories" "rijig/internal/services" "rijig/middleware" - "rijig/utils" + + // "rijig/utils" "github.com/gofiber/fiber/v2" ) @@ -15,12 +16,15 @@ func CollectorRouter(api fiber.Router) { repo := repositories.NewCollectorRepository(config.DB) repoReq := repositories.NewRequestPickupRepository(config.DB) repoAddress := repositories.NewAddressRepository(config.DB) - colectorService := services.NewCollectorService(repo, repoReq, repoAddress) + repoUser := repositories.NewUserProfilRepository(config.DB) + colectorService := services.NewCollectorService(repo, repoReq, repoAddress, repoUser) collectorHandler := handler.NewCollectorHandler(colectorService) collector := api.Group("/collector") - collector.Use(middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RolePengepul)) + collector.Use(middleware.AuthMiddleware) collector.Put("confirmrequest/:id", collectorHandler.ConfirmRequestPickup) + collector.Put("confirm-manual/request/:request_id", collectorHandler.ConfirmRequestManualPickup) + collector.Get("/avaible", collectorHandler.GetAvaibleCollector) } diff --git a/presentation/requestpickup_route.go b/presentation/requestpickup_route.go index e06e983..1ef168a 100644 --- a/presentation/requestpickup_route.go +++ b/presentation/requestpickup_route.go @@ -11,13 +11,20 @@ import ( ) func RequestPickupRouter(api fiber.Router) { + // repo repositories.RequestPickupRepository + // repoColl repositories.CollectorRepository + // repoAddress repositories.AddressRepository + // repoTrash repositories.TrashRepository + // repoUser repositories.UserProfilRepository requestRepo := repositories.NewRequestPickupRepository(config.DB) - repoTrash := repositories.NewTrashRepository(config.DB) + repoColl := repositories.NewCollectorRepository(config.DB) repoAddress := repositories.NewAddressRepository(config.DB) + Trashrepo := repositories.NewTrashRepository(config.DB) + repouser := repositories.NewUserProfilRepository(config.DB) // collectorRepo := repositories.NewCollectorRepository(config.DB) - requestPickupServices := services.NewRequestPickupService(requestRepo, repoAddress, repoTrash) + requestPickupServices := services.NewRequestPickupService(requestRepo, repoColl, repoAddress, Trashrepo, repouser) // collectorService := services.NewCollectorService(collectorRepo, requestRepo, repoAddress) // service services.RequestPickupService, // collectorService services.CollectorService @@ -30,6 +37,7 @@ func RequestPickupRouter(api fiber.Router) { requestPickupAPI.Post("/", requestPickupHandler.CreateRequestPickup) // requestPickupAPI.Get("/get", middleware.AuthMiddleware, requestPickupHandler.GetAutomaticRequestByUser) requestPickupAPI.Get("/get-allrequest", requestPickupHandler.GetRequestPickups) + requestPickupAPI.Patch("/select-collector", requestPickupHandler.AssignCollectorToRequest) // requestPickupAPI.Get("/:id", requestPickupHandler.GetRequestPickupByID) // requestPickupAPI.Get("/", requestPickupHandler.GetAllRequestPickups) // requestPickupAPI.Put("/:id", requestPickupHandler.UpdateRequestPickup) diff --git a/presentation/trash_route.go b/presentation/trash_route.go index 064bf98..1d738fa 100644 --- a/presentation/trash_route.go +++ b/presentation/trash_route.go @@ -17,16 +17,17 @@ func TrashRouter(api fiber.Router) { trashHandler := handler.NewTrashHandler(trashService) trashAPI := api.Group("/trash") + trashAPI.Use(middleware.AuthMiddleware) - trashAPI.Post("/category", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.CreateCategory) - trashAPI.Post("/category/detail", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.AddDetailToCategory) - trashAPI.Get("/categories", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), trashHandler.GetCategories) - trashAPI.Get("/category/:category_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), trashHandler.GetCategoryByID) - trashAPI.Get("/detail/:detail_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator, utils.RolePengelola, utils.RolePengepul), trashHandler.GetTrashDetailByID) + trashAPI.Post("/category", middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.CreateCategory) + trashAPI.Post("/category/detail", middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.AddDetailToCategory) + trashAPI.Get("/categories", trashHandler.GetCategories) + trashAPI.Get("/category/:category_id", trashHandler.GetCategoryByID) + trashAPI.Get("/detail/:detail_id", trashHandler.GetTrashDetailByID) - trashAPI.Patch("/category/:category_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.UpdateCategory) - trashAPI.Put("/detail/:detail_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.UpdateDetail) + trashAPI.Patch("/category/:category_id", middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.UpdateCategory) + trashAPI.Put("/detail/:detail_id", middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.UpdateDetail) - trashAPI.Delete("/category/:category_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.DeleteCategory) - trashAPI.Delete("/detail/:detail_id", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.DeleteDetail) + trashAPI.Delete("/category/:category_id", middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.DeleteCategory) + trashAPI.Delete("/detail/:detail_id", middleware.RoleMiddleware(utils.RoleAdministrator), trashHandler.DeleteDetail) } diff --git a/router/setup_routes.go.go b/router/setup_routes.go.go index 9b99496..2bf1491 100644 --- a/router/setup_routes.go.go +++ b/router/setup_routes.go.go @@ -11,10 +11,11 @@ import ( ) func SetupRoutes(app *fiber.App) { + apa := app.Group(os.Getenv("BASE_URL")) + apa.Static("/uploads", "./public"+os.Getenv("BASE_URL")+"/uploads") api := app.Group(os.Getenv("BASE_URL")) api.Use(middleware.APIKeyMiddleware) - api.Static("/uploads", "./public"+os.Getenv("BASE_URL")+"/uploads") // || auth router || // // presentation.AuthRouter(api) @@ -41,4 +42,5 @@ func SetupRoutes(app *fiber.App) { presentation.CoverageAreaRouter(api) presentation.StoreRouter(api) presentation.ProductRouter(api) + }