MIF_E31222379_BE/internal/services/requestpickup_service.go

350 lines
10 KiB
Go

package services
import (
"fmt"
"rijig/dto"
"rijig/internal/repositories"
"rijig/model"
"rijig/utils"
)
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
}
type requestPickupService struct {
repo repositories.RequestPickupRepository
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,
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) {
errors, valid := request.ValidateRequestPickup()
if !valid {
return nil, fmt.Errorf("validation errors: %v", errors)
}
_, err := s.repoAddress.FindAddressByID(request.AddressID)
if err != nil {
return nil, fmt.Errorf("address with ID %s not found", request.AddressID)
}
existingRequest, err := s.repo.FindRequestPickupByAddressAndStatus(UserId, "waiting_collector", "otomatis")
if err != nil {
return nil, fmt.Errorf("error checking for existing request pickup: %v", err)
}
if existingRequest != nil {
return nil, fmt.Errorf("there is already a pending pickup request for address %s", request.AddressID)
}
modelRequest := model.RequestPickup{
UserId: UserId,
AddressId: request.AddressID,
EvidenceImage: request.EvidenceImage,
RequestMethod: request.RequestMethod,
}
err = s.repo.CreateRequestPickup(&modelRequest)
if err != nil {
return nil, fmt.Errorf("failed to create request pickup: %v", err)
}
createdAt, _ := utils.FormatDateToIndonesianFormat(modelRequest.CreatedAt)
updatedAt, _ := utils.FormatDateToIndonesianFormat(modelRequest.UpdatedAt)
response := &dto.ResponseRequestPickup{
ID: modelRequest.ID,
UserId: UserId,
AddressID: modelRequest.AddressId,
EvidenceImage: modelRequest.EvidenceImage,
StatusPickup: modelRequest.StatusPickup,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
}
for _, item := range request.RequestItems {
findTrashCategory, err := s.repoTrash.GetCategoryByID(item.TrashCategoryID)
if err != nil {
return nil, fmt.Errorf("trash category with ID %s not found", item.TrashCategoryID)
}
modelItem := model.RequestPickupItem{
RequestPickupId: modelRequest.ID,
TrashCategoryId: findTrashCategory.ID,
EstimatedAmount: item.EstimatedAmount,
}
err = s.repo.CreateRequestPickupItem(&modelItem)
if err != nil {
return nil, fmt.Errorf("failed to create request pickup item: %v", err)
}
response.RequestItems = append(response.RequestItems, dto.ResponseRequestPickupItem{
ID: modelItem.ID,
TrashCategory: []dto.ResponseTrashCategoryDTO{{Name: findTrashCategory.Name, Icon: findTrashCategory.Icon}},
EstimatedAmount: modelItem.EstimatedAmount,
})
}
return response, nil
}
func (s *requestPickupService) GetRequestPickupByID(id string) (*dto.ResponseRequestPickup, error) {
request, err := s.repo.FindRequestPickupByID(id)
if err != nil {
return nil, fmt.Errorf("error fetching request pickup with ID %s: %v", id, err)
}
createdAt, _ := utils.FormatDateToIndonesianFormat(request.CreatedAt)
updatedAt, _ := utils.FormatDateToIndonesianFormat(request.UpdatedAt)
response := &dto.ResponseRequestPickup{
ID: request.ID,
UserId: request.UserId,
AddressID: request.AddressId,
EvidenceImage: request.EvidenceImage,
StatusPickup: request.StatusPickup,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
}
return response, nil
}
func (s *requestPickupService) GetAllRequestPickups(userid string) ([]dto.ResponseRequestPickup, error) {
requests, err := s.repo.FindAllRequestPickups(userid)
if err != nil {
return nil, fmt.Errorf("error fetching all request pickups: %v", err)
}
var response []dto.ResponseRequestPickup
for _, request := range requests {
createdAt, _ := utils.FormatDateToIndonesianFormat(request.CreatedAt)
updatedAt, _ := utils.FormatDateToIndonesianFormat(request.UpdatedAt)
response = append(response, dto.ResponseRequestPickup{
ID: request.ID,
UserId: request.UserId,
AddressID: request.AddressId,
EvidenceImage: request.EvidenceImage,
StatusPickup: request.StatusPickup,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
})
}
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)
}
var response []dto.ResponseRequestPickup
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: collector.Address.Latitude, Lon: collector.Address.Longitude},
utils.Coord{Lat: req.Address.Latitude, Lon: req.Address.Longitude},
)
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"),
}
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) 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
}