diff --git a/config/database.go b/config/database.go index 95c9859..d19ebbd 100644 --- a/config/database.go +++ b/config/database.go @@ -43,6 +43,7 @@ func ConnectDatabase() { // =>user preparation<= &model.User{}, &model.Collector{}, + &model.AvaibleTrashByCollector{}, &model.Role{}, &model.UserPin{}, &model.Address{}, diff --git a/dto/collector_dto.go b/dto/collector_dto.go index 21e89c5..a48033a 100644 --- a/dto/collector_dto.go +++ b/dto/collector_dto.go @@ -1,10 +1,22 @@ package dto -import "strings" +import ( + "fmt" + "strings" +) type RequestCollectorDTO struct { - UserId string `json:"user_id"` - AddressId string `json:"address_id"` + AddressId string `json:"address_id"` + AvaibleTrashbyCollector []RequestAvaibleTrashbyCollector `json:"avaible_trash"` +} + +type RequestAvaibleTrashbyCollector struct { + TrashId string `json:"trash_id"` + TrashPrice float32 `json:"trash_price"` +} + +type RequestAddAvaibleTrash struct { + AvaibleTrash []RequestAvaibleTrashbyCollector `json:"avaible_trash"` } type SelectCollectorRequest struct { @@ -24,25 +36,65 @@ func (r *SelectCollectorRequest) ValidateSelectCollectorRequest() (map[string][] return nil, true } -type ResponseCollectorDTO struct { - 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 *RequestAddAvaibleTrash) ValidateRequestAddAvaibleTrash() (map[string][]string, bool) { + errors := make(map[string][]string) + + if len(r.AvaibleTrash) == 0 { + errors["avaible_trash"] = append(errors["avaible_trash"], "tidak boleh kosong") + } + + for i, trash := range r.AvaibleTrash { + if strings.TrimSpace(trash.TrashId) == "" { + errors[fmt.Sprintf("avaible_trash[%d].trash_id", i)] = append(errors[fmt.Sprintf("avaible_trash[%d].trash_id", i)], "trash_id tidak boleh kosong") + } + if trash.TrashPrice <= 0 { + errors[fmt.Sprintf("avaible_trash[%d].trash_price", i)] = append(errors[fmt.Sprintf("avaible_trash[%d].trash_price", i)], "trash_price harus lebih dari 0") + } + } + + if len(errors) > 0 { + return errors, false + } + return nil, true } -func (r *RequestCollectorDTO) ValidateRequestColector() (map[string][]string, bool) { +type ResponseCollectorDTO struct { + 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"` + AvaibleTrashbyCollector []ResponseAvaibleTrashByCollector `json:"avaible_trash"` +} + +type ResponseAvaibleTrashByCollector struct { + ID string `json:"id"` + TrashId string `json:"trash_id"` + TrashName string `json:"trash_name"` + TrashIcon string `json:"trash_icon"` + TrashPrice float32 `json:"trash_price"` +} + +func (r *RequestCollectorDTO) ValidateRequestCollector() (map[string][]string, bool) { errors := make(map[string][]string) if strings.TrimSpace(r.AddressId) == "" { errors["address_id"] = append(errors["address_id"], "address_id harus diisi") } + + for i, trash := range r.AvaibleTrashbyCollector { + if strings.TrimSpace(trash.TrashId) == "" { + errors[fmt.Sprintf("avaible_trash[%d].trash_id", i)] = append(errors[fmt.Sprintf("avaible_trash[%d].trash_id", i)], "trash_id tidak boleh kosong") + } + if trash.TrashPrice <= 0 { + errors[fmt.Sprintf("avaible_trash[%d].trash_price", i)] = append(errors[fmt.Sprintf("avaible_trash[%d].trash_price", i)], "trash_price harus lebih dari 0") + } + } + if len(errors) > 0 { return errors, false } - return nil, true } diff --git a/dto/trashcart_dto.go b/dto/trashcart_dto.go index e955600..3f4a541 100644 --- a/dto/trashcart_dto.go +++ b/dto/trashcart_dto.go @@ -33,14 +33,14 @@ type CartItemResponse struct { } type RequestCartItems struct { - TrashID string `json:"trashid"` - Amount float32 `json:"amount"` + TrashCategoryID string `json:"trashid"` + Amount float32 `json:"amount"` } func (r *RequestCartItems) ValidateRequestCartItem() (map[string][]string, bool) { errors := make(map[string][]string) - if strings.TrimSpace(r.TrashID) == "" { + if strings.TrimSpace(r.TrashCategoryID) == "" { errors["trashid"] = append(errors["trashid"], "trashid is required") } @@ -58,7 +58,7 @@ type BulkRequestCartItems struct { func (b *BulkRequestCartItems) Validate() (map[string][]string, bool) { errors := make(map[string][]string) for i, item := range b.Items { - if strings.TrimSpace(item.TrashID) == "" { + if strings.TrimSpace(item.TrashCategoryID) == "" { errors[fmt.Sprintf("items[%d].trashid", i)] = append(errors[fmt.Sprintf("items[%d].trashid", i)], "trashid is required") } } diff --git a/internal/handler/collector_handler.go b/internal/handler/collector_handler.go index 355c8be..aad6c5d 100644 --- a/internal/handler/collector_handler.go +++ b/internal/handler/collector_handler.go @@ -1,7 +1,7 @@ package handler import ( - "fmt" + "context" "rijig/dto" "rijig/internal/services" "rijig/utils" @@ -9,62 +9,244 @@ import ( "github.com/gofiber/fiber/v2" ) -type CollectorHandler struct { +type CollectorHandler interface { + CreateCollector(c *fiber.Ctx) error + AddTrashToCollector(c *fiber.Ctx) error + GetCollectorByID(c *fiber.Ctx) error + GetCollectorByUserID(c *fiber.Ctx) error + UpdateCollector(c *fiber.Ctx) error + UpdateJobStatus(c *fiber.Ctx) error + UpdateTrash(c *fiber.Ctx) error + DeleteTrash(c *fiber.Ctx) error +} +type collectorHandler struct { service services.CollectorService } -func NewCollectorHandler(service services.CollectorService) *CollectorHandler { - return &CollectorHandler{service} +func NewCollectorHandler(service services.CollectorService) CollectorHandler { + return &collectorHandler{service: service} } -func (h *CollectorHandler) ConfirmRequestPickup(c *fiber.Ctx) error { +// func (h *CollectorHandler) ConfirmRequestPickup(c *fiber.Ctx) error { - collectorId, ok := c.Locals("userID").(string) - if !ok || collectorId == "" { +// collectorId, ok := c.Locals("userID").(string) +// if !ok || collectorId == "" { +// return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found") +// } + +// requestPickupId := c.Params("id") +// if requestPickupId == "" { +// return utils.ErrorResponse(c, "RequestPickup ID is required") +// } + +// req, err := h.service.ConfirmRequestPickup(requestPickupId, collectorId) +// if err != nil { +// return utils.ErrorResponse(c, err.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") +// } + +func (h *collectorHandler) CreateCollector(c *fiber.Ctx) error { + var req dto.RequestCollectorDTO + if err := c.BodyParser(&req); err != nil { + return utils.ValidationErrorResponse(c, map[string][]string{ + "body": {"format JSON tidak valid"}, + }) + } + + if errs, valid := req.ValidateRequestCollector(); !valid { + return utils.ValidationErrorResponse(c, errs) + } + + userID := c.Locals("userID").(string) + err := h.service.CreateCollector(context.Background(), userID, req) + if err != nil { + return utils.InternalServerErrorResponse(c, err.Error()) + } + + return utils.CreateResponse(c, nil, "Collector berhasil dibuat") +} + +// POST /collectors/:id/trash +func (h *collectorHandler) AddTrashToCollector(c *fiber.Ctx) error { + collectorID := c.Params("id") + var req dto.RequestAddAvaibleTrash + + if err := c.BodyParser(&req); err != nil { + return utils.ValidationErrorResponse(c, map[string][]string{ + "body": {"format JSON tidak valid"}, + }) + } + + if errs, valid := req.ValidateRequestAddAvaibleTrash(); !valid { + return utils.ValidationErrorResponse(c, errs) + } + + err := h.service.AddTrashToCollector(context.Background(), collectorID, req) + if err != nil { + return utils.InternalServerErrorResponse(c, err.Error()) + } + + return utils.SuccessResponse(c, nil, "Trash berhasil ditambahkan") +} + +// GET /collectors/:id +func (h *collectorHandler) GetCollectorByID(c *fiber.Ctx) error { + collectorID := c.Params("id") + result, err := h.service.GetCollectorByID(context.Background(), collectorID) + if err != nil { + return utils.ErrorResponse(c, "Collector tidak ditemukan") + } + return utils.SuccessResponse(c, result, "Data collector berhasil diambil") +} +func (h *collectorHandler) GetCollectorByUserID(c *fiber.Ctx) error { + // collectorID := c.Params("id") + userID, ok := c.Locals("userID").(string) + if !ok || userID == "" { return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found") } - requestPickupId := c.Params("id") - if requestPickupId == "" { - return utils.ErrorResponse(c, "RequestPickup ID is required") - } - - req, err := h.service.ConfirmRequestPickup(requestPickupId, collectorId) + result, err := h.service.GetCollectorByUserID(context.Background(), userID) if err != nil { - return utils.ErrorResponse(c, err.Error()) + return utils.ErrorResponse(c, "Collector tidak ditemukan") } - - return utils.SuccessResponse(c, req, "Request pickup confirmed successfully") + return utils.SuccessResponse(c, result, "Data collector berhasil diambil") } -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()) +// PATCH /collectors/:id +func (h *collectorHandler) UpdateCollector(c *fiber.Ctx) error { + collectorID := c.Params("id") + var req struct { + JobStatus *string `json:"job_status"` + Rating float32 `json:"rating"` + AddressID string `json:"address_id"` } - return utils.SuccessResponse(c, requests, "menampilkan data collector terdekat") + if err := c.BodyParser(&req); err != nil { + return utils.ValidationErrorResponse(c, map[string][]string{ + "body": {"format JSON tidak valid"}, + }) + } + + if req.AddressID == "" { + return utils.ValidationErrorResponse(c, map[string][]string{ + "address_id": {"tidak boleh kosong"}, + }) + } + + err := h.service.UpdateCollector(context.Background(), collectorID, req.JobStatus, req.Rating, req.AddressID) + if err != nil { + return utils.InternalServerErrorResponse(c, err.Error()) + } + + return utils.SuccessResponse(c, nil, "Collector berhasil diperbarui") } -func (h *CollectorHandler) ConfirmRequestManualPickup(c *fiber.Ctx) error { - userId := c.Locals("userID").(string) - requestId := c.Params("request_id") - if requestId == "" { - fmt.Println("requestid dibutuhkan") +func (h *collectorHandler) UpdateJobStatus(c *fiber.Ctx) error { + collectorID := c.Params("id") + var req struct { + JobStatus string `json:"job_status"` } - var request dto.SelectCollectorRequest - if err := c.BodyParser(&request); err != nil { - return fmt.Errorf("error parsing request body: %v", err) + if err := c.BodyParser(&req); err != nil { + return utils.ValidationErrorResponse(c, map[string][]string{ + "body": {"format JSON tidak valid"}, + }) } - message, err := h.service.ConfirmRequestManualPickup(requestId, userId) + if req.JobStatus != "active" && req.JobStatus != "inactive" { + return utils.ValidationErrorResponse(c, map[string][]string{ + "job_status": {"harus bernilai 'active' atau 'inactive'"}, + }) + } + + err := h.service.UpdateCollector(c.Context(), collectorID, &req.JobStatus, 0, "") if err != nil { - return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Error confirming pickup: %v", err)) + return utils.InternalServerErrorResponse(c, err.Error()) } - return utils.SuccessResponse(c, message, "berhasil konfirmasi request") + return utils.SuccessResponse(c, nil, "Status collector berhasil diperbarui") +} + + +// PATCH /collectors/:id/trash +func (h *collectorHandler) UpdateTrash(c *fiber.Ctx) error { + collectorID := c.Params("id") + var req []dto.RequestAvaibleTrashbyCollector + + if err := c.BodyParser(&req); err != nil { + return utils.ValidationErrorResponse(c, map[string][]string{ + "body": {"format JSON tidak valid"}, + }) + } + + for i, t := range req { + if t.TrashId == "" { + return utils.ValidationErrorResponse(c, map[string][]string{ + "trash_id": {t.TrashId, "trash_id tidak boleh kosong pada item ke " + string(rune(i))}, + }) + } + if t.TrashPrice <= 0 { + return utils.ValidationErrorResponse(c, map[string][]string{ + "trash_price": {"trash_price harus lebih dari 0 pada item ke " + string(rune(i))}, + }) + } + } + + err := h.service.UpdateAvaibleTrashByCollector(context.Background(), collectorID, req) + if err != nil { + return utils.InternalServerErrorResponse(c, err.Error()) + } + + return utils.SuccessResponse(c, nil, "Trash berhasil diperbarui") +} + +// DELETE /collectors/trash/:id +func (h *collectorHandler) DeleteTrash(c *fiber.Ctx) error { + trashID := c.Params("id") + if trashID == "" { + return utils.ValidationErrorResponse(c, map[string][]string{ + "trash_id": {"tidak boleh kosong"}, + }) + } + + err := h.service.DeleteAvaibleTrash(context.Background(), trashID) + if err != nil { + return utils.InternalServerErrorResponse(c, err.Error()) + } + + return utils.SuccessResponse(c, nil, "Trash berhasil dihapus") } diff --git a/internal/handler/requestpickup_handler.go b/internal/handler/requestpickup_handler.go index 0984cd2..4ae4d72 100644 --- a/internal/handler/requestpickup_handler.go +++ b/internal/handler/requestpickup_handler.go @@ -1,92 +1,92 @@ package handler -import ( - "fmt" - "rijig/dto" - "rijig/internal/services" - "rijig/utils" +// import ( +// "fmt" +// "rijig/dto" +// "rijig/internal/services" +// "rijig/utils" - "github.com/gofiber/fiber/v2" -) +// "github.com/gofiber/fiber/v2" +// ) -type RequestPickupHandler struct { - service services.RequestPickupService -} +// type RequestPickupHandler struct { +// service services.RequestPickupService +// } -func NewRequestPickupHandler(service services.RequestPickupService) *RequestPickupHandler { - return &RequestPickupHandler{service: service} -} +// func NewRequestPickupHandler(service services.RequestPickupService) *RequestPickupHandler { +// return &RequestPickupHandler{service: service} +// } -func (h *RequestPickupHandler) CreateRequestPickup(c *fiber.Ctx) error { - userID, ok := c.Locals("userID").(string) - if !ok || userID == "" { - return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found") - } +// func (h *RequestPickupHandler) CreateRequestPickup(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.RequestPickup +// var request dto.RequestPickup - if err := c.BodyParser(&request); err != nil { - return utils.GenericResponse(c, fiber.StatusBadRequest, "Invalid request body") - } +// if err := c.BodyParser(&request); err != nil { +// return utils.GenericResponse(c, fiber.StatusBadRequest, "Invalid request body") +// } - errors, valid := request.ValidateRequestPickup() - if !valid { - return utils.ValidationErrorResponse(c, errors) - } +// errors, valid := request.ValidateRequestPickup() +// if !valid { +// return utils.ValidationErrorResponse(c, errors) +// } - response, err := h.service.CreateRequestPickup(request, userID) - if err != nil { - return utils.InternalServerErrorResponse(c, fmt.Sprintf("Error creating request pickup: %v", err)) - } +// response, err := h.service.CreateRequestPickup(request, userID) +// if err != nil { +// return utils.InternalServerErrorResponse(c, fmt.Sprintf("Error creating request pickup: %v", err)) +// } - return utils.SuccessResponse(c, response, "Request pickup created successfully") -} +// return utils.SuccessResponse(c, response, "Request pickup created successfully") +// } -func (h *RequestPickupHandler) GetRequestPickupByID(c *fiber.Ctx) error { - id := c.Params("id") +// func (h *RequestPickupHandler) GetRequestPickupByID(c *fiber.Ctx) error { +// id := c.Params("id") - response, err := h.service.GetRequestPickupByID(id) - if err != nil { - return utils.GenericResponse(c, fiber.StatusNotFound, fmt.Sprintf("Request pickup with ID %s not found: %v", id, err)) - } +// response, err := h.service.GetRequestPickupByID(id) +// if err != nil { +// return utils.GenericResponse(c, fiber.StatusNotFound, fmt.Sprintf("Request pickup with ID %s not found: %v", id, err)) +// } - return utils.SuccessResponse(c, response, "Request pickup retrieved successfully") -} +// return utils.SuccessResponse(c, response, "Request pickup retrieved successfully") +// } -func (h *RequestPickupHandler) GetRequestPickups(c *fiber.Ctx) error { +// func (h *RequestPickupHandler) GetRequestPickups(c *fiber.Ctx) error { - collectorId := c.Locals("userID").(string) +// collectorId := c.Locals("userID").(string) - requests, err := h.service.GetRequestPickupsForCollector(collectorId) - if err != nil { - return utils.ErrorResponse(c, err.Error()) - } +// requests, err := h.service.GetRequestPickupsForCollector(collectorId) +// if err != nil { +// return utils.ErrorResponse(c, err.Error()) +// } - return utils.SuccessResponse(c, requests, "Automatic request pickups retrieved successfully") -} +// return utils.SuccessResponse(c, requests, "Automatic request pickups retrieved successfully") +// } -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") - } +// 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) - } +// 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) - } +// 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 { +// err := h.service.SelectCollectorInRequest(userId, request.Collector_id) +// if err != nil { - return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Error assigning collector: %v", err)) - } +// return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Error assigning collector: %v", err)) +// } - return utils.GenericResponse(c, fiber.StatusOK, "berhasil memilih collector") -} +// return utils.GenericResponse(c, fiber.StatusOK, "berhasil memilih collector") +// } diff --git a/internal/repositories/collector_repo.go b/internal/repositories/collector_repo.go index 5f0ef53..9340893 100644 --- a/internal/repositories/collector_repo.go +++ b/internal/repositories/collector_repo.go @@ -1,115 +1,177 @@ package repositories import ( + "context" "errors" - "fmt" - "log" - "rijig/model" - "gorm.io/gorm" + // "fmt" + + // "log" + "rijig/config" + "rijig/model" + // "gorm.io/gorm" ) 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) + // 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) + + CreateCollector(ctx context.Context, collector *model.Collector) error + AddAvaibleTrash(ctx context.Context, trashItems []model.AvaibleTrashByCollector) error + GetCollectorByID(ctx context.Context, collectorID string) (*model.Collector, error) + GetCollectorByUserID(ctx context.Context, userID string) (*model.Collector, error) + GetTrashItemByID(ctx context.Context, id string) (*model.AvaibleTrashByCollector, error) + UpdateCollector(ctx context.Context, collector *model.Collector, updates map[string]interface{}) error + UpdateAvaibleTrashByCollector(ctx context.Context, collectorID string, updatedTrash []model.AvaibleTrashByCollector) error + DeleteAvaibleTrash(ctx context.Context, trashID string) error } type collectorRepository struct { - DB *gorm.DB + // DB *gorm.DB } -func NewCollectorRepository(db *gorm.DB) CollectorRepository { - return &collectorRepository{DB: db} +// func NewCollectorRepository(db *gorm.DB) CollectorRepository { +// return &collectorRepository{DB: db} +// } +func NewCollectorRepository() CollectorRepository { + return &collectorRepository{} } -func (r *collectorRepository) FindActiveCollectors() ([]model.Collector, error) { - var collectors []model.Collector +// func (r *collectorRepository) FindActiveCollectors() ([]model.Collector, error) { +// var collectors []model.Collector - 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) +// 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) +// } + +// return collectors, nil +// } + +// 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 { +// return nil, fmt.Errorf("error fetching collector: %v", err) +// } +// fmt.Printf("menampilkan data collector %v", &collector) +// return &collector, nil +// } + +// func (r *collectorRepository) CreateCollector(collector *model.Collector) error { +// if err := r.DB.Create(collector).Error; err != nil { +// return fmt.Errorf("failed to create collector: %v", err) +// } +// return nil +// } + +// func (r *collectorRepository) UpdateCollector(userId string, jobStatus string) (*model.Collector, error) { +// var existingCollector model.Collector + +// if err := r.DB.Where("user_id = ?", userId).First(&existingCollector).Error; err != nil { +// if errors.Is(err, gorm.ErrRecordNotFound) { +// return nil, fmt.Errorf("collector dengan user_id %s tidak ditemukan", userId) +// } +// log.Printf("Gagal mencari collector: %v", err) +// return nil, fmt.Errorf("gagal fetching collector: %w", err) +// } + +// if jobStatus != "active" && jobStatus != "nonactive" { +// return nil, fmt.Errorf("invalid job status: %v", jobStatus) +// } + +// if err := r.DB.Model(&existingCollector).Update("jobstatus", jobStatus).Error; err != nil { +// log.Printf("Gagal mengupdate data collector: %v", err) +// return nil, fmt.Errorf("gagal mengupdate job status untuk collector: %w", err) +// } + +// return &existingCollector, nil +// } + +func (r *collectorRepository) CreateCollector(ctx context.Context, collector *model.Collector) error { + return config.DB.WithContext(ctx).Create(collector).Error +} + +func (r *collectorRepository) AddAvaibleTrash(ctx context.Context, trashItems []model.AvaibleTrashByCollector) error { + if len(trashItems) == 0 { + return nil } - - return collectors, nil + return config.DB.WithContext(ctx).Create(&trashItems).Error } -func (r *collectorRepository) FindCollectorById(collector_id string) (*model.Collector, error) { +func (r *collectorRepository) GetCollectorByID(ctx context.Context, collectorID string) (*model.Collector, error) { var collector model.Collector - err := r.DB.Preload("Address").Where("user_id = ?", collector_id).First(&collector).Error + err := config.DB.WithContext(ctx). + Preload("User"). + Preload("Address"). + Preload("AvaibleTrashByCollector.TrashCategory"). + First(&collector, "id = ?", collectorID).Error + if err != nil { - return nil, fmt.Errorf("error fetching collector: %v", err) + return nil, err } - fmt.Printf("menampilkan data collector %v", &collector) return &collector, nil } -func (r *collectorRepository) FindCollectorByIdWithoutAddr(collector_id string) (*model.Collector, error) { +func (r *collectorRepository) GetCollectorByUserID(ctx context.Context, userID string) (*model.Collector, error) { var collector model.Collector - err := r.DB.Where("user_id = ?", collector_id).First(&collector).Error + err := config.DB.WithContext(ctx). + Preload("User"). + Preload("Address"). + Preload("AvaibleTrashByCollector.TrashCategory"). + First(&collector, "user_id = ?", userID).Error + if err != nil { - return nil, fmt.Errorf("error fetching collector: %v", err) + return nil, err } - fmt.Printf("menampilkan data collector %v", &collector) return &collector, nil } -func (r *collectorRepository) CreateCollector(collector *model.Collector) error { - if err := r.DB.Create(collector).Error; err != nil { - return fmt.Errorf("failed to create collector: %v", err) +func (r *collectorRepository) GetTrashItemByID(ctx context.Context, id string) (*model.AvaibleTrashByCollector, error) { + var item model.AvaibleTrashByCollector + if err := config.DB.WithContext(ctx).First(&item, "id = ?", id).Error; err != nil { + return nil, err + } + return &item, nil +} + +func (r *collectorRepository) UpdateCollector(ctx context.Context, collector *model.Collector, updates map[string]interface{}) error { + return config.DB.WithContext(ctx). + Model(&model.Collector{}). + Where("id = ?", collector.ID). + Updates(updates).Error +} + +func (r *collectorRepository) UpdateAvaibleTrashByCollector(ctx context.Context, collectorID string, updatedTrash []model.AvaibleTrashByCollector) error { + for _, trash := range updatedTrash { + err := config.DB.WithContext(ctx). + Model(&model.AvaibleTrashByCollector{}). + Where("collector_id = ? AND trash_category_id = ?", collectorID, trash.TrashCategoryID). + Update("price", trash.Price).Error + if err != nil { + return err + } } return nil } -func (r *collectorRepository) UpdateCollector(userId string, jobStatus string) (*model.Collector, error) { - var existingCollector model.Collector - - if err := r.DB.Where("user_id = ?", userId).First(&existingCollector).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, fmt.Errorf("collector dengan user_id %s tidak ditemukan", userId) - } - log.Printf("Gagal mencari collector: %v", err) - return nil, fmt.Errorf("gagal fetching collector: %w", err) +func (r *collectorRepository) DeleteAvaibleTrash(ctx context.Context, trashID string) error { + if trashID == "" { + return errors.New("trash_id cannot be empty") } - - if jobStatus != "active" && jobStatus != "nonactive" { - return nil, fmt.Errorf("invalid job status: %v", jobStatus) - } - - if err := r.DB.Model(&existingCollector).Update("jobstatus", jobStatus).Error; err != nil { - log.Printf("Gagal mengupdate data collector: %v", err) - return nil, fmt.Errorf("gagal mengupdate job status untuk collector: %w", err) - } - - return &existingCollector, nil + return config.DB.WithContext(ctx). + Delete(&model.AvaibleTrashByCollector{}, "id = ?", trashID).Error } - -// // #====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) -// } - -// 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) - -// if km <= maxDistance { -// nearbyRequests = append(nearbyRequests, request) -// } -// } - -// return nearbyRequests, nil -// } diff --git a/internal/repositories/trash_repo.go b/internal/repositories/trash_repo.go index 99a5e1d..4b88d35 100644 --- a/internal/repositories/trash_repo.go +++ b/internal/repositories/trash_repo.go @@ -1,10 +1,12 @@ package repositories import ( + "context" "errors" "fmt" "log" + "rijig/config" "rijig/model" "gorm.io/gorm" @@ -22,6 +24,7 @@ type TrashRepository interface { UpdateCategoryName(id string, newName string) error UpdateCategory(id string, updateTrashCategory *model.TrashCategory) (*model.TrashCategory, error) UpdateTrashDetail(id string, description string, price float64) error + UpdateEstimatedPrice(ctx context.Context, trashCategoryID string) error DeleteCategory(id string) error DeleteTrashDetail(id string) error } @@ -131,6 +134,23 @@ func (r *trashRepository) UpdateTrashDetail(id string, description string, price return nil } +func (r *trashRepository) UpdateEstimatedPrice(ctx context.Context, trashCategoryID string) error { + var avg float64 + + err := config.DB.WithContext(ctx). + Model(&model.AvaibleTrashByCollector{}). + Where("trash_category_id = ?", trashCategoryID). + Select("AVG(price)").Scan(&avg).Error + if err != nil { + return err + } + + return config.DB.WithContext(ctx). + Model(&model.TrashCategory{}). + Where("id = ?", trashCategoryID). + Update("estimated_price", avg).Error +} + func (r *trashRepository) DeleteCategory(id string) error { if err := r.DB.Delete(&model.TrashCategory{}, "id = ?", id).Error; err != nil { return fmt.Errorf("failed to delete category: %v", err) diff --git a/internal/services/collector_service.go b/internal/services/collector_service.go index 9cf745e..0984d31 100644 --- a/internal/services/collector_service.go +++ b/internal/services/collector_service.go @@ -1,151 +1,224 @@ package services import ( - "fmt" + "context" + "errors" + "rijig/dto" "rijig/internal/repositories" - "rijig/utils" - "time" + "rijig/model" ) type CollectorService interface { - FindCollectorsNearby(userId string) ([]dto.ResponseCollectorDTO, error) - ConfirmRequestPickup(requestId, collectorId string) (*dto.ResponseRequestPickup, error) - ConfirmRequestManualPickup(requestId, collectorId string) (any, error) + CreateCollector(ctx context.Context, userID string, req dto.RequestCollectorDTO) error + AddTrashToCollector(ctx context.Context, collectorID string, req dto.RequestAddAvaibleTrash) error + GetCollectorByID(ctx context.Context, collectorID string) (*dto.ResponseCollectorDTO, error) + GetCollectorByUserID(ctx context.Context, userID string) (*dto.ResponseCollectorDTO, error) + UpdateCollector(ctx context.Context, collectorID string, jobStatus *string, rating float32, addressID string) error + UpdateAvaibleTrashByCollector(ctx context.Context, collectorID string, updatedTrash []dto.RequestAvaibleTrashbyCollector) error + DeleteAvaibleTrash(ctx context.Context, trashID string) error } type collectorService struct { - repo repositories.CollectorRepository - repoColl repositories.RequestPickupRepository - repoAddress repositories.AddressRepository - repoUser repositories.UserProfilRepository + repo repositories.CollectorRepository + trashRepo repositories.TrashRepository } -func NewCollectorService(repo repositories.CollectorRepository, - repoColl repositories.RequestPickupRepository, - repoAddress repositories.AddressRepository, - repoUser repositories.UserProfilRepository) CollectorService { - return &collectorService{repo: repo, repoColl: repoColl, repoAddress: repoAddress, repoUser: repoUser} +func NewCollectorService(repo repositories.CollectorRepository, trashRepo repositories.TrashRepository, + +) CollectorService { + + return &collectorService{repo: repo, trashRepo: trashRepo} } -func (s *collectorService) FindCollectorsNearby(userId string) ([]dto.ResponseCollectorDTO, error) { - collectors, err := s.repo.FindActiveCollectors() - if err != nil { - return nil, fmt.Errorf("error fetching active collectors: %v", err) +func (s *collectorService) CreateCollector(ctx context.Context, userID string, req dto.RequestCollectorDTO) error { + collector := &model.Collector{ + UserID: userID, + AddressID: req.AddressId, + JobStatus: "inactive", + Rating: 5, } - var avaibleCollectResp []dto.ResponseCollectorDTO - - for _, collector := range collectors { - - request, err := s.repoColl.FindRequestPickupByAddressAndStatus(userId, "waiting_collector", "otomatis") - if err != nil { - return nil, fmt.Errorf("gagal mendapatkan data request pickup dengan userid: %v", err) - } - - _, distance := utils.Distance( - utils.Coord{Lat: request.Address.Latitude, Lon: request.Address.Longitude}, - utils.Coord{Lat: collector.Address.Latitude, Lon: collector.Address.Longitude}, - ) - - if distance <= 20 { - - mappedRequest := dto.ResponseCollectorDTO{ - ID: collector.ID, - 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 err := s.repo.CreateCollector(ctx, collector); err != nil { + return err } - return avaibleCollectResp, nil + var trashItems []model.AvaibleTrashByCollector + for _, item := range req.AvaibleTrashbyCollector { + trashItems = append(trashItems, model.AvaibleTrashByCollector{ + CollectorID: collector.ID, + TrashCategoryID: item.TrashId, + Price: item.TrashPrice, + }) + } + + if err := s.repo.AddAvaibleTrash(ctx, trashItems); err != nil { + return err + } + + for _, t := range trashItems { + _ = s.trashRepo.UpdateEstimatedPrice(ctx, t.TrashCategoryID) + } + + return nil } -func (s *collectorService) ConfirmRequestPickup(requestId, collectorId string) (*dto.ResponseRequestPickup, error) { - request, err := s.repoColl.FindRequestPickupByID(requestId) - if err != nil { - return nil, fmt.Errorf("request pickup not found: %v", err) +func (s *collectorService) AddTrashToCollector(ctx context.Context, collectorID string, req dto.RequestAddAvaibleTrash) error { + var trashItems []model.AvaibleTrashByCollector + for _, item := range req.AvaibleTrash { + trashItems = append(trashItems, model.AvaibleTrashByCollector{ + CollectorID: collectorID, + TrashCategoryID: item.TrashId, + Price: item.TrashPrice, + }) + } + if err := s.repo.AddAvaibleTrash(ctx, trashItems); err != nil { + return err } - if request.StatusPickup != "waiting_collector" { - return nil, fmt.Errorf("pickup request is not in 'waiting_collector' status") + for _, t := range trashItems { + _ = s.trashRepo.UpdateEstimatedPrice(ctx, t.TrashCategoryID) } - collector, err := s.repo.FindCollectorById(collectorId) - if err != nil { - return nil, fmt.Errorf("collector tidak ditemukan: %v", err) - } - - request.StatusPickup = "confirmed" - request.CollectorID = &collector.ID - *request.ConfirmedByCollectorAt = time.Now() - - 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) - - response := dto.ResponseRequestPickup{ - StatusPickup: request.StatusPickup, - CollectorID: *request.CollectorID, - ConfirmedByCollectorAt: confirmedAt, - } - - return &response, nil + return nil } -func (s *collectorService) ConfirmRequestManualPickup(requestId, collectorId string) (any, error) { - - request, err := s.repoColl.FindRequestPickupByID(requestId) +func (s *collectorService) GetCollectorByID(ctx context.Context, collectorID string) (*dto.ResponseCollectorDTO, error) { + collector, err := s.repo.GetCollectorByID(ctx, collectorID) if err != nil { - return nil, fmt.Errorf("collector tidak ditemukan: %v", err) + return nil, err } - coll, err := s.repo.FindCollectorByIdWithoutAddr(collectorId) + response := &dto.ResponseCollectorDTO{ + ID: collector.ID, + UserId: collector.UserID, + AddressId: collector.AddressID, + JobStatus: &collector.JobStatus, + Rating: collector.Rating, + User: &dto.UserResponseDTO{ + ID: collector.User.ID, + Name: collector.User.Name, + Phone: collector.User.Phone, + }, + Address: &dto.AddressResponseDTO{ + Province: collector.Address.Province, + District: collector.Address.District, + Regency: collector.Address.Regency, + Village: collector.Address.Village, + PostalCode: collector.Address.PostalCode, + Latitude: collector.Address.Latitude, + Longitude: collector.Address.Longitude, + }, + } + + for _, item := range collector.AvaibleTrashByCollector { + response.AvaibleTrashbyCollector = append(response.AvaibleTrashbyCollector, dto.ResponseAvaibleTrashByCollector{ + ID: item.ID, + TrashId: item.TrashCategory.ID, + TrashName: item.TrashCategory.Name, + TrashIcon: item.TrashCategory.Icon, + TrashPrice: item.Price, + }) + } + + return response, nil +} + +func (s *collectorService) GetCollectorByUserID(ctx context.Context, userID string) (*dto.ResponseCollectorDTO, error) { + collector, err := s.repo.GetCollectorByUserID(ctx, userID) if err != nil { - return nil, fmt.Errorf("%v", err) + return nil, err } - if coll.ID != *request.CollectorID { - return nil, fmt.Errorf("collectorid tidak sesuai dengan request") + response := &dto.ResponseCollectorDTO{ + ID: collector.ID, + UserId: collector.UserID, + AddressId: collector.AddressID, + JobStatus: &collector.JobStatus, + Rating: collector.Rating, + User: &dto.UserResponseDTO{ + ID: collector.User.ID, + Name: collector.User.Name, + Phone: collector.User.Phone, + }, + Address: &dto.AddressResponseDTO{ + Province: collector.Address.Province, + District: collector.Address.District, + Regency: collector.Address.Regency, + Village: collector.Address.Village, + PostalCode: collector.Address.PostalCode, + Latitude: collector.Address.Latitude, + Longitude: collector.Address.Longitude, + }, } - request.StatusPickup = "confirmed" - *request.ConfirmedByCollectorAt = time.Now() + for _, item := range collector.AvaibleTrashByCollector { + response.AvaibleTrashbyCollector = append(response.AvaibleTrashbyCollector, dto.ResponseAvaibleTrashByCollector{ + ID: item.ID, + TrashId: item.TrashCategory.ID, + TrashName: item.TrashCategory.Name, + TrashIcon: item.TrashCategory.Icon, + TrashPrice: item.Price, + }) + } - err = s.repoColl.UpdateRequestPickup(requestId, request) + return response, nil +} + +func (s *collectorService) UpdateCollector(ctx context.Context, collectorID string, jobStatus *string, rating float32, addressID string) error { + updates := make(map[string]interface{}) + + if jobStatus != nil { + updates["job_status"] = *jobStatus + } + if rating > 0 { + updates["rating"] = rating + } + if addressID != "" { + updates["address_id"] = addressID + } + + if len(updates) == 0 { + return errors.New("tidak ada data yang diubah") + } + + return s.repo.UpdateCollector(ctx, &model.Collector{ID: collectorID}, updates) +} + +func (s *collectorService) UpdateAvaibleTrashByCollector(ctx context.Context, collectorID string, updatedTrash []dto.RequestAvaibleTrashbyCollector) error { + var updated []model.AvaibleTrashByCollector + for _, item := range updatedTrash { + updated = append(updated, model.AvaibleTrashByCollector{ + CollectorID: collectorID, + TrashCategoryID: item.TrashId, + Price: item.TrashPrice, + }) + } + + if err := s.repo.UpdateAvaibleTrashByCollector(ctx, collectorID, updated); err != nil { + return err + } + + for _, item := range updated { + _ = s.trashRepo.UpdateEstimatedPrice(ctx, item.TrashCategoryID) + } + + return nil +} + +func (s *collectorService) DeleteAvaibleTrash(ctx context.Context, trashID string) error { + if trashID == "" { + return errors.New("trash_id tidak boleh kosong") + } + + item, err := s.repo.GetTrashItemByID(ctx, trashID) if err != nil { - return nil, fmt.Errorf("failed to update request pickup: %v", err) + return err } - return "berhasil konfirmasi request pickup", nil -} \ No newline at end of file + if err := s.repo.DeleteAvaibleTrash(ctx, trashID); err != nil { + return err + } + + return s.trashRepo.UpdateEstimatedPrice(ctx, item.TrashCategoryID) +} diff --git a/internal/services/requestpickup_service.go b/internal/services/requestpickup_service.go index f79996d..8656d06 100644 --- a/internal/services/requestpickup_service.go +++ b/internal/services/requestpickup_service.go @@ -9,11 +9,11 @@ import ( ) type RequestPickupService interface { - CreateRequestPickup(request dto.RequestPickup, UserId string) (*dto.ResponseRequestPickup, error) - GetRequestPickupByID(id string) (*dto.ResponseRequestPickup, error) - GetAllRequestPickups(userid string) ([]dto.ResponseRequestPickup, error) - GetRequestPickupsForCollector(collectorId string) ([]dto.ResponseRequestPickup, error) - SelectCollectorInRequest(userId, collectorId string) error + // CreateRequestPickup(request dto.RequestPickup, UserId string) (*dto.ResponseRequestPickup, error) + // GetRequestPickupByID(id string) (*dto.ResponseRequestPickup, error) + // GetAllRequestPickups(userid string) ([]dto.ResponseRequestPickup, error) + // GetRequestPickupsForCollector(collectorId string) ([]dto.ResponseRequestPickup, error) + // SelectCollectorInRequest(userId, collectorId string) error } type requestPickupService struct { @@ -152,198 +152,198 @@ func (s *requestPickupService) GetAllRequestPickups(userid string) ([]dto.Respon return response, nil } -func (s *requestPickupService) GetRequestPickupsForCollector(collectorId string) ([]dto.ResponseRequestPickup, error) { - requests, err := s.repo.GetAutomaticRequestPickupsForCollector() - if err != nil { - return nil, fmt.Errorf("error retrieving automatic pickup requests: %v", err) - } +// func (s *requestPickupService) GetRequestPickupsForCollector(collectorId string) ([]dto.ResponseRequestPickup, error) { +// requests, err := s.repo.GetAutomaticRequestPickupsForCollector() +// if err != nil { +// return nil, fmt.Errorf("error retrieving automatic pickup requests: %v", err) +// } - var response []dto.ResponseRequestPickup +// var response []dto.ResponseRequestPickup - for _, req := range requests { +// for _, req := range requests { - collector, err := s.repoColl.FindCollectorById(collectorId) - if err != nil { - return nil, fmt.Errorf("error fetching collector data: %v", err) - } +// 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: collector.Address.Latitude, Lon: collector.Address.Longitude}, - utils.Coord{Lat: req.Address.Latitude, Lon: req.Address.Longitude}, - ) +// _, distance := utils.Distance( +// utils.Coord{Lat: collector.Address.Latitude, Lon: collector.Address.Longitude}, +// utils.Coord{Lat: req.Address.Latitude, Lon: req.Address.Longitude}, +// ) - if distance <= 20 { +// if distance <= 20 { - mappedRequest := dto.ResponseRequestPickup{ - ID: req.ID, - UserId: req.UserId, - AddressID: req.AddressId, - EvidenceImage: req.EvidenceImage, - StatusPickup: req.StatusPickup, - CreatedAt: req.CreatedAt.Format("2006-01-02 15:04:05"), - UpdatedAt: req.UpdatedAt.Format("2006-01-02 15:04:05"), - } +// mappedRequest := dto.ResponseRequestPickup{ +// ID: req.ID, +// UserId: req.UserId, +// AddressID: req.AddressId, +// EvidenceImage: req.EvidenceImage, +// StatusPickup: req.StatusPickup, +// CreatedAt: req.CreatedAt.Format("2006-01-02 15:04:05"), +// 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, - }, - } +// 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, - }, - } +// 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) - } +// requestItems, err := s.repo.GetRequestPickupItems(req.ID) +// if err != nil { +// return nil, fmt.Errorf("error fetching request items: %v", err) +// } - var mappedRequestItems []dto.ResponseRequestPickupItem +// 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) - } +// 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, - }) - } +// mappedRequestItems = append(mappedRequestItems, dto.ResponseRequestPickupItem{ +// ID: item.ID, +// TrashCategory: []dto.ResponseTrashCategoryDTO{{ +// Name: trashCategory.Name, +// Icon: trashCategory.Icon, +// }}, +// EstimatedAmount: item.EstimatedAmount, +// }) +// } - mappedRequest.RequestItems = mappedRequestItems +// mappedRequest.RequestItems = mappedRequestItems - response = append(response, mappedRequest) - } - } +// response = append(response, mappedRequest) +// } +// } - return response, nil -} +// return response, nil +// } -func (s *requestPickupService) GetManualRequestPickupsForCollector(collectorId string) ([]dto.ResponseRequestPickup, error) { +// 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) - } +// 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 +// var response []dto.ResponseRequestPickup - for _, req := range requests { +// for _, req := range requests { - createdAt, _ := utils.FormatDateToIndonesianFormat(req.CreatedAt) - updatedAt, _ := utils.FormatDateToIndonesianFormat(req.UpdatedAt) +// 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, - } +// 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, - }, - } +// 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, - }, - } +// 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) - } +// requestItems, err := s.repo.GetRequestPickupItems(req.ID) +// if err != nil { +// return nil, fmt.Errorf("error fetching request items: %v", err) +// } - var mappedRequestItems []dto.ResponseRequestPickupItem +// var mappedRequestItems []dto.ResponseRequestPickupItem - for _, item := range requestItems { +// for _, item := range requestItems { - trashCategory, err := s.repoTrash.GetCategoryByID(item.TrashCategoryId) - if err != nil { - return nil, fmt.Errorf("error fetching trash category: %v", err) - } +// 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, - }) - } +// mappedRequestItems = append(mappedRequestItems, dto.ResponseRequestPickupItem{ +// ID: item.ID, +// TrashCategory: []dto.ResponseTrashCategoryDTO{{ +// Name: trashCategory.Name, +// Icon: trashCategory.Icon, +// }}, +// EstimatedAmount: item.EstimatedAmount, +// }) +// } - mappedRequest.RequestItems = mappedRequestItems +// mappedRequest.RequestItems = mappedRequestItems - response = append(response, mappedRequest) - } +// response = append(response, mappedRequest) +// } - return response, nil -} +// return response, nil +// } -func (s *requestPickupService) SelectCollectorInRequest(userId, collectorId string) error { +// 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) - } +// 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") - } +// 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) - } +// collector, err := s.repoColl.FindCollectorByIdWithoutAddr(collectorId) +// if err != nil { +// return fmt.Errorf("collector tidak ditemukan: %v", err) +// } - request.CollectorID = &collector.ID +// request.CollectorID = &collector.ID - err = s.repo.UpdateRequestPickup(request.ID, request) - if err != nil { - return fmt.Errorf("failed to update request pickup: %v", err) - } +// err = s.repo.UpdateRequestPickup(request.ID, request) +// if err != nil { +// return fmt.Errorf("failed to update request pickup: %v", err) +// } - return nil -} +// return nil +// } diff --git a/internal/services/trashcart_redisservices.go b/internal/services/trashcart_redisservices.go index a19b149..12b1a12 100644 --- a/internal/services/trashcart_redisservices.go +++ b/internal/services/trashcart_redisservices.go @@ -30,7 +30,7 @@ func GetCartItems(userID string) ([]dto.RequestCartItems, error) { if err != nil { return nil, err } - + return items, nil } @@ -45,7 +45,7 @@ func AddOrUpdateCartItem(userID string, newItem dto.RequestCartItems) error { updated := false for i, item := range cartItems { - if item.TrashID == newItem.TrashID { + if item.TrashCategoryID == newItem.TrashCategoryID { if newItem.Amount == 0 { cartItems = append(cartItems[:i], cartItems[i+1:]...) } else { @@ -80,14 +80,14 @@ func DeleteCartItem(userID, trashID string) error { index := -1 for i, item := range items { - if item.TrashID == trashID { + if item.TrashCategoryID == trashID { index = i break } } if index == -1 { - log.Printf("TrashID %s not found in cart for user %s", trashID, userID) + log.Printf("TrashCategoryID %s not found in cart for user %s", trashID, userID) return fmt.Errorf("trashid not found") } diff --git a/internal/services/trashcart_service.go b/internal/services/trashcart_service.go index 04ebfd4..b8442a6 100644 --- a/internal/services/trashcart_service.go +++ b/internal/services/trashcart_service.go @@ -31,9 +31,9 @@ func (s *CartService) CommitCartToDatabase(userID string) error { var estimatedTotal float32 for _, item := range items { - trash, err := s.Repo.GetTrashCategoryByID(item.TrashID) + trash, err := s.Repo.GetTrashCategoryByID(item.TrashCategoryID) if err != nil { - log.Printf("Trash category not found for trashID: %s", item.TrashID) + log.Printf("Trash category not found for trashID: %s", item.TrashCategoryID) continue } @@ -43,7 +43,7 @@ func (s *CartService) CommitCartToDatabase(userID string) error { cartItems = append(cartItems, model.CartItem{ ID: uuid.NewString(), - TrashID: item.TrashID, + TrashCategoryID: item.TrashCategoryID, Amount: item.Amount, SubTotalEstimatedPrice: subTotal, }) @@ -87,7 +87,7 @@ func (s *CartService) GetCartFromRedis(userID string) (*dto.CartResponse, error) var cartItemDTOs []dto.CartItemResponse for _, item := range items { - trash, err := s.Repo.GetTrashCategoryByID(item.TrashID) + trash, err := s.Repo.GetTrashCategoryByID(item.TrashCategoryID) if err != nil { continue } @@ -133,7 +133,7 @@ func (s *CartService) GetCart(userID string) (*dto.CartResponse, error) { for _, item := range cartDB.CartItems { items = append(items, dto.CartItemResponse{ ItemId: item.ID, - TrashId: item.TrashID, + TrashId: item.TrashCategoryID, TrashIcon: item.TrashCategory.Icon, TrashName: item.TrashCategory.Name, Amount: item.Amount, diff --git a/model/collector_model.go b/model/collector_model.go index 009ed98..4000cad 100644 --- a/model/collector_model.go +++ b/model/collector_model.go @@ -1,16 +1,25 @@ package model +import "time" + 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: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"` + ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"` + UserID string `gorm:"not null" json:"user_id"` + User User `gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-"` + 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"` + AvaibleTrashByCollector []AvaibleTrashByCollector `gorm:"foreignKey:CollectorID;constraint:OnDelete:CASCADE;" json:"avaible_trash"` + CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"` + UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"` } -// job_status { -// "active", -// "inactive" -// } +type AvaibleTrashByCollector struct { + ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"` + CollectorID string `gorm:"not null" json:"collector_id"` + Collector *Collector `gorm:"foreignKey:CollectorID;constraint:OnDelete:CASCADE;" json:"-"` + TrashCategoryID string `gorm:"not null" json:"trash_id"` + TrashCategory TrashCategory `gorm:"foreignKey:TrashCategoryID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"trash_category"` + Price float32 `json:"price"` +} diff --git a/model/trashcart_model.go b/model/trashcart_model.go index 97aa8d0..bfe1467 100644 --- a/model/trashcart_model.go +++ b/model/trashcart_model.go @@ -11,17 +11,18 @@ type Cart struct { CartItems []CartItem `gorm:"foreignKey:CartID;constraint:OnDelete:CASCADE;" json:"cartitems"` TotalAmount float32 `json:"totalamount"` EstimatedTotalPrice float32 `json:"estimated_totalprice"` - CreatedAt time.Time `gorm:"autoCreateTime" json:"createdAt"` - UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updatedAt"` + CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"` + UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"` } type CartItem struct { ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"` CartID string `gorm:"not null" json:"-"` - TrashID string `gorm:"not null" json:"trashid"` - TrashCategory TrashCategory `gorm:"foreignKey:TrashID;constraint:OnDelete:CASCADE;" json:"trash"` + Cart *Cart `gorm:"foreignKey:CartID;constraint:OnDelete:CASCADE;" json:"-"` + TrashCategoryID string `gorm:"not null" json:"trash_id"` + TrashCategory TrashCategory `gorm:"foreignKey:TrashCategoryID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"trash_category"` Amount float32 `json:"amount"` SubTotalEstimatedPrice float32 `json:"subtotalestimatedprice"` - CreatedAt time.Time `gorm:"autoCreateTime" json:"createdAt"` - UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updatedAt"` + CreatedAt time.Time `gorm:"default:current_timestamp" json:"created_at"` + UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updated_at"` } diff --git a/presentation/collector_route.go b/presentation/collector_route.go index 93692b9..06f200a 100644 --- a/presentation/collector_route.go +++ b/presentation/collector_route.go @@ -13,18 +13,39 @@ import ( ) func CollectorRouter(api fiber.Router) { - repo := repositories.NewCollectorRepository(config.DB) - repoReq := repositories.NewRequestPickupRepository(config.DB) - repoAddress := repositories.NewAddressRepository(config.DB) - repoUser := repositories.NewUserProfilRepository(config.DB) - colectorService := services.NewCollectorService(repo, repoReq, repoAddress, repoUser) - collectorHandler := handler.NewCollectorHandler(colectorService) + // repo := repositories.NewCollectorRepository(config.DB) + // repoReq := repositories.NewRequestPickupRepository(config.DB) + // repoAddress := repositories.NewAddressRepository(config.DB) + // repoUser := repositories.NewUserProfilRepository(config.DB) + // colectorService := services.NewCollectorService(repo, repoReq, repoAddress, repoUser) + // collectorHandler := handler.NewCollectorHandler(colectorService) - collector := api.Group("/collector") - collector.Use(middleware.AuthMiddleware) + // collector := api.Group("/collector") + // collector.Use(middleware.AuthMiddleware) - collector.Put("confirmrequest/:id", collectorHandler.ConfirmRequestPickup) - collector.Put("confirm-manual/request/:request_id", collectorHandler.ConfirmRequestManualPickup) - collector.Get("/avaible", collectorHandler.GetAvaibleCollector) + // collector.Put("confirmrequest/:id", collectorHandler.ConfirmRequestPickup) + // collector.Put("confirm-manual/request/:request_id", collectorHandler.ConfirmRequestManualPickup) + // collector.Get("/avaible", collectorHandler.GetAvaibleCollector) + // Middleware Auth dan Role + + // Inisialisasi repository dan service + collectorRepo := repositories.NewCollectorRepository() + trashRepo := repositories.NewTrashRepository(config.DB) + collectorService := services.NewCollectorService(collectorRepo, trashRepo) + collectorHandler := handler.NewCollectorHandler(collectorService) + + // Group collector + collectors := api.Group("/collectors") + collectors.Use(middleware.AuthMiddleware) + + // === Collector routes === + collectors.Post("/", collectorHandler.CreateCollector) // Create collector + collectors.Post("/:id/trash", collectorHandler.AddTrashToCollector) // Add trash to collector + collectors.Get("/:id", collectorHandler.GetCollectorByID) // Get collector by ID + collectors.Get("/", collectorHandler.GetCollectorByUserID) // Get collector by ID + collectors.Patch("/:id", collectorHandler.UpdateCollector) // Update collector fields + collectors.Patch("/:id/trash", collectorHandler.UpdateTrash) + collectors.Patch("/:id/job-status", collectorHandler.UpdateJobStatus) + collectors.Delete("/trash/:id", collectorHandler.DeleteTrash) } diff --git a/presentation/requestpickup_route.go b/presentation/requestpickup_route.go index 1ef168a..029826a 100644 --- a/presentation/requestpickup_route.go +++ b/presentation/requestpickup_route.go @@ -1,45 +1,46 @@ package presentation -import ( - "rijig/config" - "rijig/internal/handler" - "rijig/internal/repositories" - "rijig/internal/services" - "rijig/middleware" +// import ( +// "rijig/config" +// "rijig/internal/handler" +// "rijig/internal/repositories" +// "rijig/internal/services" +// "rijig/middleware" - "github.com/gofiber/fiber/v2" -) +// "github.com/gofiber/fiber/v2" +// ) -func RequestPickupRouter(api fiber.Router) { - // repo repositories.RequestPickupRepository - // repoColl repositories.CollectorRepository - // repoAddress repositories.AddressRepository - // repoTrash repositories.TrashRepository - // repoUser repositories.UserProfilRepository +// 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) - 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) +// requestRepo := repositories.NewRequestPickupRepository(config.DB) +// // repoColl := repositories.NewCollectorRepository(config.DB) +// repoColl := repositories.NewCollectorRepository() +// repoAddress := repositories.NewAddressRepository(config.DB) +// Trashrepo := repositories.NewTrashRepository(config.DB) +// repouser := repositories.NewUserProfilRepository(config.DB) +// // collectorRepo := repositories.NewCollectorRepository(config.DB) - requestPickupServices := services.NewRequestPickupService(requestRepo, repoColl, repoAddress, Trashrepo, repouser) - // collectorService := services.NewCollectorService(collectorRepo, requestRepo, repoAddress) - // service services.RequestPickupService, - // collectorService services.CollectorService +// requestPickupServices := services.NewRequestPickupService(requestRepo, repoColl, repoAddress, Trashrepo, repouser) +// // collectorService := services.NewCollectorService(collectorRepo, requestRepo, repoAddress) +// // service services.RequestPickupService, +// // collectorService services.CollectorService - requestPickupHandler := handler.NewRequestPickupHandler(requestPickupServices) +// requestPickupHandler := handler.NewRequestPickupHandler(requestPickupServices) - requestPickupAPI := api.Group("/requestpickup") - requestPickupAPI.Use(middleware.AuthMiddleware) +// requestPickupAPI := api.Group("/requestpickup") +// requestPickupAPI.Use(middleware.AuthMiddleware) - 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) - // requestPickupAPI.Delete("/:id", requestPickupHandler.DeleteRequestPickup) -} +// 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) +// // requestPickupAPI.Delete("/:id", requestPickupHandler.DeleteRequestPickup) +// } diff --git a/router/setup_routes.go.go b/router/setup_routes.go.go index d23059d..4c7e163 100644 --- a/router/setup_routes.go.go +++ b/router/setup_routes.go.go @@ -26,7 +26,7 @@ func SetupRoutes(app *fiber.App) { // || auth router || // presentation.IdentityCardRouter(api) presentation.CompanyProfileRouter(api) - presentation.RequestPickupRouter(api) + // presentation.RequestPickupRouter(api) presentation.CollectorRouter(api) presentation.TrashCartRouter(api)