diff --git a/internal/handler/wilayah_indonesia_handler.go b/internal/handler/wilayah_indonesia_handler.go index d2d582a..bb09a78 100644 --- a/internal/handler/wilayah_indonesia_handler.go +++ b/internal/handler/wilayah_indonesia_handler.go @@ -1,7 +1,6 @@ package handler import ( - "fmt" "strconv" "github.com/gofiber/fiber/v2" @@ -27,122 +26,163 @@ func (h *WilayahIndonesiaHandler) ImportWilayahData(c *fiber.Ctx) error { return utils.GenericErrorResponse(c, fiber.StatusCreated, "Data imported successfully") } -func (h *WilayahIndonesiaHandler) GetAllProvinces(c *fiber.Ctx) error { - page, err := strconv.Atoi(c.Query("page", "1")) +func (h *WilayahIndonesiaHandler) GetProvinces(c *fiber.Ctx) error { + + page, err := strconv.Atoi(c.Query("page", "0")) if err != nil { - page = 1 + page = 0 + } + limit, err := strconv.Atoi(c.Query("limit", "0")) + if err != nil { + limit = 0 } - limit, err := strconv.Atoi(c.Query("limit", "10")) + provinces, totalProvinces, err := h.WilayahService.GetAllProvinces(page, limit) if err != nil { - limit = 10 + return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, "Failed to fetch provinces") } - provinces, err := h.WilayahService.GetAllProvinces(page, limit) - if err != nil { - return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, fmt.Sprintf("Failed to fetch provinces: %v", err)) + if page > 0 && limit > 0 { + return utils.PaginatedResponse(c, provinces, page, limit, totalProvinces, "Provinces fetched successfully") } - return utils.PaginatedResponse(c, provinces, page, limit, len(provinces), "Provinces fetched successfully") + return utils.NonPaginatedResponse(c, provinces, totalProvinces, "Provinces fetched successfully") } func (h *WilayahIndonesiaHandler) GetProvinceByID(c *fiber.Ctx) error { provinceID := c.Params("id") - province, err := h.WilayahService.GetProvinceByID(provinceID) + page, err := strconv.Atoi(c.Query("page", "0")) if err != nil { - return utils.GenericErrorResponse(c, fiber.StatusNotFound, fmt.Sprintf("Province not found: %v", err)) + page = 0 + } + limit, err := strconv.Atoi(c.Query("limit", "0")) + if err != nil { + limit = 0 } - return utils.LogResponse(c, province, "Province fetched successfully") + province, totalRegencies, err := h.WilayahService.GetProvinceByID(provinceID, page, limit) + if err != nil { + return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, "Failed to fetch province") + } + + if page > 0 && limit > 0 { + return utils.PaginatedResponse(c, province, page, limit, totalRegencies, "Province fetched successfully") + } + + return utils.NonPaginatedResponse(c, province, totalRegencies, "Province fetched successfully") } func (h *WilayahIndonesiaHandler) GetAllRegencies(c *fiber.Ctx) error { - page, err := strconv.Atoi(c.Query("page", "1")) + page, err := strconv.Atoi(c.Query("page", "0")) if err != nil { - page = 1 + page = 0 + } + limit, err := strconv.Atoi(c.Query("limit", "0")) + if err != nil { + limit = 0 } - limit, err := strconv.Atoi(c.Query("limit", "10")) + regencies, totalRegencies, err := h.WilayahService.GetAllRegencies(page, limit) if err != nil { - limit = 10 + return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, "Failed to fetch regency") } - regencies, err := h.WilayahService.GetAllRegencies(page, limit) - if err != nil { - return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, fmt.Sprintf("Failed to fetch regencies: %v", err)) + if page > 0 && limit > 0 { + return utils.PaginatedResponse(c, regencies, page, limit, totalRegencies, "regency fetched successfully") } - return utils.PaginatedResponse(c, regencies, page, limit, len(regencies), "Regencies fetched successfully") + return utils.NonPaginatedResponse(c, regencies, totalRegencies, "Provinces fetched successfully") } func (h *WilayahIndonesiaHandler) GetRegencyByID(c *fiber.Ctx) error { - regencyID := c.Params("id") + regencyId := c.Params("id") - regency, err := h.WilayahService.GetRegencyByID(regencyID) + page, err := strconv.Atoi(c.Query("page", "0")) if err != nil { - return utils.GenericErrorResponse(c, fiber.StatusNotFound, fmt.Sprintf("Regency not found: %v", err)) + page = 0 + } + limit, err := strconv.Atoi(c.Query("limit", "0")) + if err != nil { + limit = 0 } - return utils.LogResponse(c, regency, "Regency fetched successfully") + regency, totalDistrict, err := h.WilayahService.GetRegencyByID(regencyId, page, limit) + if err != nil { + return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, "Failed to fetch regency") + } + + if page > 0 && limit > 0 { + return utils.PaginatedResponse(c, regency, page, limit, totalDistrict, "regency fetched successfully") + } + + return utils.NonPaginatedResponse(c, regency, totalDistrict, "regency fetched successfully") } func (h *WilayahIndonesiaHandler) GetAllDistricts(c *fiber.Ctx) error { - page, err := strconv.Atoi(c.Query("page", "1")) + page, err := strconv.Atoi(c.Query("page", "0")) if err != nil { - page = 1 + page = 0 + } + limit, err := strconv.Atoi(c.Query("limit", "0")) + if err != nil { + limit = 0 } - limit, err := strconv.Atoi(c.Query("limit", "10")) + districts, totalDistricts, err := h.WilayahService.GetAllDistricts(page, limit) if err != nil { - limit = 10 + return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, "Failed to fetch districts") } - districts, err := h.WilayahService.GetAllDistricts(page, limit) - if err != nil { - return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, fmt.Sprintf("Failed to fetch districts: %v", err)) + if page > 0 && limit > 0 { + return utils.PaginatedResponse(c, districts, page, limit, totalDistricts, "districts fetched successfully") } - return utils.PaginatedResponse(c, districts, page, limit, len(districts), "Districts fetched successfully") + return utils.NonPaginatedResponse(c, districts, totalDistricts, "districts fetched successfully") } func (h *WilayahIndonesiaHandler) GetDistrictByID(c *fiber.Ctx) error { - districtID := c.Params("id") + districtId := c.Params("id") - district, err := h.WilayahService.GetDistrictByID(districtID) + page, err := strconv.Atoi(c.Query("page", "0")) if err != nil { - return utils.GenericErrorResponse(c, fiber.StatusNotFound, fmt.Sprintf("District not found: %v", err)) + page = 0 + } + limit, err := strconv.Atoi(c.Query("limit", "0")) + if err != nil { + limit = 0 } - return utils.LogResponse(c, district, "District fetched successfully") + district, totalVillages, err := h.WilayahService.GetDistrictByID(districtId, page, limit) + if err != nil { + return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, "Failed to fetch district") + } + + if page > 0 && limit > 0 { + return utils.PaginatedResponse(c, district, page, limit, totalVillages, "district fetched successfully") + } + + return utils.NonPaginatedResponse(c, district, totalVillages, "district fetched successfully") } func (h *WilayahIndonesiaHandler) GetAllVillages(c *fiber.Ctx) error { - page, err := strconv.Atoi(c.Query("page", "1")) + page, err := strconv.Atoi(c.Query("page", "0")) if err != nil { - page = 1 + page = 0 + } + limit, err := strconv.Atoi(c.Query("limit", "0")) + if err != nil { + limit = 0 } - limit, err := strconv.Atoi(c.Query("limit", "10")) + villages, totalVillages, err := h.WilayahService.GetAllVillages(page, limit) if err != nil { - limit = 10 + return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, "Failed to fetch villages") } - villages, err := h.WilayahService.GetAllVillages(page, limit) - if err != nil { - return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, fmt.Sprintf("Failed to fetch villages: %v", err)) + if page > 0 && limit > 0 { + return utils.PaginatedResponse(c, villages, page, limit, totalVillages, "villages fetched successfully") } - return utils.PaginatedResponse(c, villages, page, limit, len(villages), "Villages fetched successfully") -} - -func (h *WilayahIndonesiaHandler) GetVillageByID(c *fiber.Ctx) error { - villageID := c.Params("id") - - village, err := h.WilayahService.GetVillageByID(villageID) - if err != nil { - return utils.GenericErrorResponse(c, fiber.StatusNotFound, fmt.Sprintf("Village not found: %v", err)) - } - - return utils.LogResponse(c, village, "Village fetched successfully") + return utils.NonPaginatedResponse(c, villages, totalVillages, "villages fetched successfully") } diff --git a/internal/repositories/wilayah_indonesia_repo.go b/internal/repositories/wilayah_indonesia_repo.go index 8fee6d8..e2d9e92 100644 --- a/internal/repositories/wilayah_indonesia_repo.go +++ b/internal/repositories/wilayah_indonesia_repo.go @@ -10,18 +10,17 @@ type WilayahIndonesiaRepository interface { ImportRegencies(regencies []model.Regency) error ImportDistricts(districts []model.District) error ImportVillages(villages []model.Village) error - // ================================================== // + FindAllProvinces(page, limit int) ([]model.Province, int, error) - FindProvinceByID(id string) (*model.Province, error) + FindProvinceByID(id string, page, limit int) (*model.Province, int, error) FindAllRegencies(page, limit int) ([]model.Regency, int, error) - FindRegencyByID(id string) (*model.Regency, error) + FindRegencyByID(id string, page, limit int) (*model.Regency, int, error) FindAllDistricts(page, limit int) ([]model.District, int, error) - FindDistrictByID(id string) (*model.District, error) + FindDistrictByID(id string, page, limit int) (*model.District, int, error) FindAllVillages(page, limit int) ([]model.Village, int, error) - FindVillageByID(id string) (*model.Village, error) } type wilayahIndonesiaRepository struct { @@ -68,127 +67,164 @@ func (r *wilayahIndonesiaRepository) ImportVillages(villages []model.Village) er return nil } -/* -| ============================================================ | -| ============================================================ | -*/ - -// FindAllProvinces with Pagination func (r *wilayahIndonesiaRepository) FindAllProvinces(page, limit int) ([]model.Province, int, error) { var provinces []model.Province var total int64 - // Count total provinces err := r.DB.Model(&model.Province{}).Count(&total).Error if err != nil { return nil, 0, err } - // Get provinces with pagination - err = r.DB.Offset((page - 1) * limit).Limit(limit).Find(&provinces).Error - if err != nil { - return nil, 0, err + if page > 0 && limit > 0 { + err := r.DB.Offset((page - 1) * limit).Limit(limit).Find(&provinces).Error + if err != nil { + return nil, 0, err + } + } else { + + err := r.DB.Find(&provinces).Error + if err != nil { + return nil, 0, err + } } return provinces, int(total), nil } -// FindProvinceByID -func (r *wilayahIndonesiaRepository) FindProvinceByID(id string) (*model.Province, error) { +func (r *wilayahIndonesiaRepository) FindProvinceByID(id string, page, limit int) (*model.Province, int, error) { var province model.Province - err := r.DB.Preload("Regencies").Where("id = ?", id).First(&province).Error + + err := r.DB.Preload("Regencies", func(db *gorm.DB) *gorm.DB { + if page > 0 && limit > 0 { + + return db.Offset((page - 1) * limit).Limit(limit) + } + + return db + }).Where("id = ?", id).First(&province).Error if err != nil { - return nil, err + return nil, 0, err } - return &province, nil + + var totalRegencies int64 + r.DB.Model(&model.Regency{}).Where("province_id = ?", id).Count(&totalRegencies) + + return &province, int(totalRegencies), nil } -// FindAllRegencies with Pagination func (r *wilayahIndonesiaRepository) FindAllRegencies(page, limit int) ([]model.Regency, int, error) { var regencies []model.Regency var total int64 - // Count total regencies err := r.DB.Model(&model.Regency{}).Count(&total).Error if err != nil { return nil, 0, err } - // Get regencies with pagination - err = r.DB.Offset((page - 1) * limit).Limit(limit).Preload("Districts").Find(®encies).Error - if err != nil { - return nil, 0, err + if page > 0 && limit > 0 { + err := r.DB.Offset((page - 1) * limit).Limit(limit).Find(®encies).Error + if err != nil { + return nil, 0, err + } + } else { + err := r.DB.Find(®encies).Error + if err != nil { + return nil, 0, err + } } return regencies, int(total), nil } -// FindRegencyByID -func (r *wilayahIndonesiaRepository) FindRegencyByID(id string) (*model.Regency, error) { +func (r *wilayahIndonesiaRepository) FindRegencyByID(id string, page, limit int) (*model.Regency, int, error) { var regency model.Regency - err := r.DB.Preload("Districts").Where("id = ?", id).First(®ency).Error + + err := r.DB.Preload("Districs", func(db *gorm.DB) *gorm.DB { + if page > 0 && limit > 0 { + + return db.Offset((page - 1) * limit).Limit(limit) + } + + return db + }).Where("id = ?", id).First(®ency).Error if err != nil { - return nil, err + return nil, 0, err } - return ®ency, nil + + var totalDistrict int64 + r.DB.Model(&model.District{}).Where("regency_id = ?", id).Count(&totalDistrict) + + return ®ency, int(totalDistrict), nil } -// FindAllDistricts with Pagination func (r *wilayahIndonesiaRepository) FindAllDistricts(page, limit int) ([]model.District, int, error) { - var districts []model.District + var district []model.District var total int64 - // Count total districts err := r.DB.Model(&model.District{}).Count(&total).Error if err != nil { return nil, 0, err } - // Get districts with pagination - err = r.DB.Offset((page - 1) * limit).Limit(limit).Preload("Villages").Find(&districts).Error + if page > 0 && limit > 0 { + err := r.DB.Offset((page - 1) * limit).Limit(limit).Find(&district).Error + if err != nil { + return nil, 0, err + } + } else { + + err := r.DB.Find(&district).Error + if err != nil { + return nil, 0, err + } + } + + return district, int(total), nil +} + +func (r *wilayahIndonesiaRepository) FindDistrictByID(id string, page, limit int) (*model.District, int, error) { + var district model.District + + err := r.DB.Preload("Village", func(db *gorm.DB) *gorm.DB { + if page > 0 && limit > 0 { + + return db.Offset((page - 1) * limit).Limit(limit) + } + + return db + }).Where("id = ?", id).First(&district).Error if err != nil { return nil, 0, err } - return districts, int(total), nil + var totalVillage int64 + r.DB.Model(&model.Village{}).Where("district_id = ?", id).Count(&totalVillage) + + return &district, int(totalVillage), nil } -// FindDistrictByID -func (r *wilayahIndonesiaRepository) FindDistrictByID(id string) (*model.District, error) { - var district model.District - err := r.DB.Preload("Villages").Where("id = ?", id).First(&district).Error - if err != nil { - return nil, err - } - return &district, nil -} - -// FindAllVillages with Pagination func (r *wilayahIndonesiaRepository) FindAllVillages(page, limit int) ([]model.Village, int, error) { - var villages []model.Village + var village []model.Village var total int64 - // Count total villages err := r.DB.Model(&model.Village{}).Count(&total).Error if err != nil { return nil, 0, err } - // Get villages with pagination - err = r.DB.Offset((page - 1) * limit).Limit(limit).Find(&villages).Error - if err != nil { - return nil, 0, err + if page > 0 && limit > 0 { + err := r.DB.Offset((page - 1) * limit).Limit(limit).Find(&village).Error + if err != nil { + return nil, 0, err + } + } else { + + err := r.DB.Find(&village).Error + if err != nil { + return nil, 0, err + } } - return villages, int(total), nil + return village, int(total), nil } - -// FindVillageByID -func (r *wilayahIndonesiaRepository) FindVillageByID(id string) (*model.Village, error) { - var village model.Village - err := r.DB.Where("id = ?", id).First(&village).Error - if err != nil { - return nil, err - } - return &village, nil -} \ No newline at end of file diff --git a/internal/services/wilayah_indonesia_service.go b/internal/services/wilayah_indonesia_service.go index 1e183c4..b3b0f70 100644 --- a/internal/services/wilayah_indonesia_service.go +++ b/internal/services/wilayah_indonesia_service.go @@ -1,7 +1,9 @@ package services import ( + "encoding/json" "fmt" + "strconv" "time" "github.com/pahmiudahgede/senggoldong/dto" @@ -13,17 +15,16 @@ import ( type WilayahIndonesiaService interface { ImportDataFromCSV() error - GetAllProvinces(page, limit int) ([]dto.ProvinceResponseDTO, error) - GetProvinceByID(id string) (*dto.ProvinceResponseDTO, error) + GetAllProvinces(page, limit int) ([]dto.ProvinceResponseDTO, int, error) + GetProvinceByID(id string, page, limit int) (*dto.ProvinceResponseDTO, int, error) - GetAllRegencies(page, limit int) ([]dto.RegencyResponseDTO, error) - GetRegencyByID(id string) (*dto.RegencyResponseDTO, error) + GetAllRegencies(page, limit int) ([]dto.RegencyResponseDTO, int, error) + GetRegencyByID(id string, page, limit int) (*dto.RegencyResponseDTO, int, error) - GetAllDistricts(page, limit int) ([]dto.DistrictResponseDTO, error) - GetDistrictByID(id string) (*dto.DistrictResponseDTO, error) + GetAllDistricts(page, limit int) ([]dto.DistrictResponseDTO, int, error) + GetDistrictByID(id string, page, limit int) (*dto.DistrictResponseDTO, int, error) - GetAllVillages(page, limit int) ([]dto.VillageResponseDTO, error) - GetVillageByID(id string) (*dto.VillageResponseDTO, error) + GetAllVillages(page, limit int) ([]dto.VillageResponseDTO, int, error) } type wilayahIndonesiaService struct { @@ -114,9 +115,9 @@ func (s *wilayahIndonesiaService) ImportDataFromCSV() error { return nil } -func (s *wilayahIndonesiaService) GetAllProvinces(page, limit int) ([]dto.ProvinceResponseDTO, error) { +func (s *wilayahIndonesiaService) GetAllProvinces(page, limit int) ([]dto.ProvinceResponseDTO, int, error) { - cacheKey := fmt.Sprintf("provinces_page_%d_limit_%d", page, limit) + cacheKey := fmt.Sprintf("provinces_page:%d_limit:%d", page, limit) cachedData, err := utils.GetJSONData(cacheKey) if err == nil && cachedData != nil { var provinces []dto.ProvinceResponseDTO @@ -130,13 +131,14 @@ func (s *wilayahIndonesiaService) GetAllProvinces(page, limit int) ([]dto.Provin }) } } - return provinces, nil + total := int(cachedData["total"].(float64)) + return provinces, total, nil } } provinces, total, err := s.WilayahRepo.FindAllProvinces(page, limit) if err != nil { - return nil, fmt.Errorf("failed to fetch provinces: %v", err) + return nil, 0, fmt.Errorf("failed to fetch provinces: %v", err) } var provinceDTOs []dto.ProvinceResponseDTO @@ -150,66 +152,68 @@ func (s *wilayahIndonesiaService) GetAllProvinces(page, limit int) ([]dto.Provin cacheData := map[string]interface{}{ "data": provinceDTOs, "total": total, - "page": page, - "limit": limit, } err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24) if err != nil { - fmt.Printf("Error caching provinces data to Redis: %v\n", err) + fmt.Printf("Error caching provinces data: %v\n", err) } - return provinceDTOs, nil + return provinceDTOs, total, nil } -func (s *wilayahIndonesiaService) GetProvinceByID(id string) (*dto.ProvinceResponseDTO, error) { +func (s *wilayahIndonesiaService) GetProvinceByID(id string, page, limit int) (*dto.ProvinceResponseDTO, int, error) { - cacheKey := fmt.Sprintf("province:%s", id) + cacheKey := fmt.Sprintf("province:%s_page:%d_limit:%d", id, page, limit) cachedData, err := utils.GetJSONData(cacheKey) if err == nil && cachedData != nil { - var province dto.ProvinceResponseDTO - if data, ok := cachedData["data"].(map[string]interface{}); ok { - province = dto.ProvinceResponseDTO{ - ID: data["id"].(string), - Name: data["name"].(string), + + var provinceDTO dto.ProvinceResponseDTO + if data, ok := cachedData["data"].(string); ok { + if err := json.Unmarshal([]byte(data), &provinceDTO); err == nil { + + totalRegencies, _ := strconv.Atoi(cachedData["total_regencies"].(string)) + return &provinceDTO, totalRegencies, nil } - return &province, nil } } - province, err := s.WilayahRepo.FindProvinceByID(id) + province, totalRegencies, err := s.WilayahRepo.FindProvinceByID(id, page, limit) if err != nil { - return nil, fmt.Errorf("failed to fetch province: %v", err) + return nil, 0, err } - provinceDTO := &dto.ProvinceResponseDTO{ + provinceDTO := dto.ProvinceResponseDTO{ ID: province.ID, Name: province.Name, } - regenciesDTO := []dto.RegencyResponseDTO{} + var regencyDTOs []dto.RegencyResponseDTO for _, regency := range province.Regencies { - regenciesDTO = append(regenciesDTO, dto.RegencyResponseDTO{ + regencyDTO := dto.RegencyResponseDTO{ ID: regency.ID, ProvinceID: regency.ProvinceID, Name: regency.Name, - }) + } + regencyDTOs = append(regencyDTOs, regencyDTO) } - provinceDTO.Regencies = regenciesDTO + + provinceDTO.Regencies = regencyDTOs cacheData := map[string]interface{}{ - "data": provinceDTO, + "data": provinceDTO, + "total_regencies": strconv.Itoa(totalRegencies), } err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24) if err != nil { - fmt.Printf("Error caching province data to Redis: %v\n", err) + fmt.Printf("Error caching province data: %v\n", err) } - return provinceDTO, nil + return &provinceDTO, totalRegencies, nil } -func (s *wilayahIndonesiaService) GetAllRegencies(page, limit int) ([]dto.RegencyResponseDTO, error) { +func (s *wilayahIndonesiaService) GetAllRegencies(page, limit int) ([]dto.RegencyResponseDTO, int, error) { - cacheKey := fmt.Sprintf("regencies_page_%d_limit_%d", page, limit) + cacheKey := fmt.Sprintf("regencies_page:%d_limit:%d", page, limit) cachedData, err := utils.GetJSONData(cacheKey) if err == nil && cachedData != nil { var regencies []dto.RegencyResponseDTO @@ -224,13 +228,14 @@ func (s *wilayahIndonesiaService) GetAllRegencies(page, limit int) ([]dto.Regenc }) } } - return regencies, nil + total := int(cachedData["total"].(float64)) + return regencies, total, nil } } regencies, total, err := s.WilayahRepo.FindAllRegencies(page, limit) if err != nil { - return nil, fmt.Errorf("failed to fetch regencies: %v", err) + return nil, 0, fmt.Errorf("failed to fetch provinces: %v", err) } var regencyDTOs []dto.RegencyResponseDTO @@ -245,68 +250,69 @@ func (s *wilayahIndonesiaService) GetAllRegencies(page, limit int) ([]dto.Regenc cacheData := map[string]interface{}{ "data": regencyDTOs, "total": total, - "page": page, - "limit": limit, } err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24) if err != nil { - fmt.Printf("Error caching regencies data to Redis: %v\n", err) + fmt.Printf("Error caching regencies data: %v\n", err) } - return regencyDTOs, nil + return regencyDTOs, total, nil } -func (s *wilayahIndonesiaService) GetRegencyByID(id string) (*dto.RegencyResponseDTO, error) { +func (s *wilayahIndonesiaService) GetRegencyByID(id string, page, limit int) (*dto.RegencyResponseDTO, int, error) { - cacheKey := fmt.Sprintf("regency:%s", id) + cacheKey := fmt.Sprintf("regency:%s_page:%d_limit:%d", id, page, limit) cachedData, err := utils.GetJSONData(cacheKey) if err == nil && cachedData != nil { - var regency dto.RegencyResponseDTO - if data, ok := cachedData["data"].(map[string]interface{}); ok { - regency = dto.RegencyResponseDTO{ - ID: data["id"].(string), - ProvinceID: data["province_id"].(string), - Name: data["name"].(string), + + var regencyDTO dto.RegencyResponseDTO + if data, ok := cachedData["data"].(string); ok { + if err := json.Unmarshal([]byte(data), ®encyDTO); err == nil { + + totalDistrict, _ := strconv.Atoi(cachedData["total_regencies"].(string)) + return ®encyDTO, totalDistrict, nil } - return ®ency, nil } } - regency, err := s.WilayahRepo.FindRegencyByID(id) + regency, totalDistrict, err := s.WilayahRepo.FindRegencyByID(id, page, limit) if err != nil { - return nil, fmt.Errorf("failed to fetch regency: %v", err) + return nil, 0, err } - regencyDTO := &dto.RegencyResponseDTO{ + regencyDTO := dto.RegencyResponseDTO{ ID: regency.ID, ProvinceID: regency.ProvinceID, Name: regency.Name, } - districtsDTO := []dto.DistrictResponseDTO{} - for _, district := range regency.Districts { - districtsDTO = append(districtsDTO, dto.DistrictResponseDTO{ - ID: district.ID, - RegencyID: district.RegencyID, - Name: district.Name, - }) + var districtDTOs []dto.DistrictResponseDTO + for _, regency := range regency.Districts { + districtDTO := dto.DistrictResponseDTO{ + ID: regency.ID, + RegencyID: regency.RegencyID, + Name: regency.Name, + } + districtDTOs = append(districtDTOs, districtDTO) } - regencyDTO.Districts = districtsDTO + + regencyDTO.Districts = districtDTOs cacheData := map[string]interface{}{ - "data": regencyDTO, + "data": regencyDTO, + "total_regencies": strconv.Itoa(totalDistrict), } err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24) if err != nil { - fmt.Printf("Error caching regency data to Redis: %v\n", err) + fmt.Printf("Error caching province data: %v\n", err) } - return regencyDTO, nil + return ®encyDTO, totalDistrict, nil } -func (s *wilayahIndonesiaService) GetAllDistricts(page, limit int) ([]dto.DistrictResponseDTO, error) { +func (s *wilayahIndonesiaService) GetAllDistricts(page, limit int) ([]dto.DistrictResponseDTO, int, error) { - cacheKey := fmt.Sprintf("districts_page_%d_limit_%d", page, limit) + cacheKey := fmt.Sprintf("district_page:%d_limit:%d", page, limit) cachedData, err := utils.GetJSONData(cacheKey) if err == nil && cachedData != nil { var districts []dto.DistrictResponseDTO @@ -321,18 +327,19 @@ func (s *wilayahIndonesiaService) GetAllDistricts(page, limit int) ([]dto.Distri }) } } - return districts, nil + total := int(cachedData["total"].(float64)) + return districts, total, nil } } districts, total, err := s.WilayahRepo.FindAllDistricts(page, limit) if err != nil { - return nil, fmt.Errorf("failed to fetch districts: %v", err) + return nil, 0, fmt.Errorf("failed to fetch districts: %v", err) } - var districtDTOs []dto.DistrictResponseDTO + var districtsDTOs []dto.DistrictResponseDTO for _, district := range districts { - districtDTOs = append(districtDTOs, dto.DistrictResponseDTO{ + districtsDTOs = append(districtsDTOs, dto.DistrictResponseDTO{ ID: district.ID, RegencyID: district.RegencyID, Name: district.Name, @@ -340,70 +347,71 @@ func (s *wilayahIndonesiaService) GetAllDistricts(page, limit int) ([]dto.Distri } cacheData := map[string]interface{}{ - "data": districtDTOs, + "data": districtsDTOs, "total": total, - "page": page, - "limit": limit, } err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24) if err != nil { - fmt.Printf("Error caching districts data to Redis: %v\n", err) + fmt.Printf("Error caching districts data: %v\n", err) } - return districtDTOs, nil + return districtsDTOs, total, nil } -func (s *wilayahIndonesiaService) GetDistrictByID(id string) (*dto.DistrictResponseDTO, error) { +func (s *wilayahIndonesiaService) GetDistrictByID(id string, page, limit int) (*dto.DistrictResponseDTO, int, error) { - cacheKey := fmt.Sprintf("district:%s", id) + cacheKey := fmt.Sprintf("district:%s_page:%d_limit:%d", id, page, limit) cachedData, err := utils.GetJSONData(cacheKey) if err == nil && cachedData != nil { - var district dto.DistrictResponseDTO - if data, ok := cachedData["data"].(map[string]interface{}); ok { - district = dto.DistrictResponseDTO{ - ID: data["id"].(string), - RegencyID: data["regency_id"].(string), - Name: data["name"].(string), + + var districtDTO dto.DistrictResponseDTO + if data, ok := cachedData["data"].(string); ok { + if err := json.Unmarshal([]byte(data), &districtDTO); err == nil { + + totalVillage, _ := strconv.Atoi(cachedData["total_village"].(string)) + return &districtDTO, totalVillage, nil } - return &district, nil } } - district, err := s.WilayahRepo.FindDistrictByID(id) + district, totalVillages, err := s.WilayahRepo.FindDistrictByID(id, page, limit) if err != nil { - return nil, fmt.Errorf("failed to fetch district: %v", err) + return nil, 0, err } - districtDTO := &dto.DistrictResponseDTO{ + districtDTO := dto.DistrictResponseDTO{ ID: district.ID, RegencyID: district.RegencyID, Name: district.Name, } - villagesDTO := []dto.VillageResponseDTO{} + var villageDTOs []dto.VillageResponseDTO for _, village := range district.Villages { - villagesDTO = append(villagesDTO, dto.VillageResponseDTO{ + regencyDTO := dto.VillageResponseDTO{ ID: village.ID, DistrictID: village.DistrictID, Name: village.Name, - }) + } + villageDTOs = append(villageDTOs, regencyDTO) } - districtDTO.Villages = villagesDTO + + districtDTO.Villages = villageDTOs cacheData := map[string]interface{}{ - "data": districtDTO, + "data": districtDTO, + "total_villages": strconv.Itoa(totalVillages), } err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24) if err != nil { - fmt.Printf("Error caching district data to Redis: %v\n", err) + fmt.Printf("Error caching province data: %v\n", err) } - return districtDTO, nil + return &districtDTO, totalVillages, nil } -func (s *wilayahIndonesiaService) GetAllVillages(page, limit int) ([]dto.VillageResponseDTO, error) { +func (s *wilayahIndonesiaService) GetAllVillages(page, limit int) ([]dto.VillageResponseDTO, int, error) { - cacheKey := fmt.Sprintf("villages:%d:%d", page, limit) + cacheKey := fmt.Sprintf("villages_page:%d_limit:%d", page, limit) cachedData, err := utils.GetJSONData(cacheKey) if err == nil && cachedData != nil { var villages []dto.VillageResponseDTO @@ -418,13 +426,14 @@ func (s *wilayahIndonesiaService) GetAllVillages(page, limit int) ([]dto.Village }) } } - return villages, nil + total := int(cachedData["total"].(float64)) + return villages, total, nil } } villages, total, err := s.WilayahRepo.FindAllVillages(page, limit) if err != nil { - return nil, fmt.Errorf("failed to fetch villages: %v", err) + return nil, 0, fmt.Errorf("failed to fetch villages: %v", err) } var villageDTOs []dto.VillageResponseDTO @@ -442,46 +451,8 @@ func (s *wilayahIndonesiaService) GetAllVillages(page, limit int) ([]dto.Village } err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24) if err != nil { - fmt.Printf("Error caching village data to Redis: %v\n", err) + fmt.Printf("Error caching villages data: %v\n", err) } - return villageDTOs, nil -} - -func (s *wilayahIndonesiaService) GetVillageByID(id string) (*dto.VillageResponseDTO, error) { - - cacheKey := fmt.Sprintf("village:%s", id) - cachedData, err := utils.GetJSONData(cacheKey) - if err == nil && cachedData != nil { - var villageDTO dto.VillageResponseDTO - if data, ok := cachedData["data"].(map[string]interface{}); ok { - villageDTO = dto.VillageResponseDTO{ - ID: data["id"].(string), - DistrictID: data["district_id"].(string), - Name: data["name"].(string), - } - return &villageDTO, nil - } - } - - village, err := s.WilayahRepo.FindVillageByID(id) - if err != nil { - return nil, fmt.Errorf("village not found: %v", err) - } - - villageDTO := &dto.VillageResponseDTO{ - ID: village.ID, - DistrictID: village.DistrictID, - Name: village.Name, - } - - cacheData := map[string]interface{}{ - "data": villageDTO, - } - err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24) - if err != nil { - fmt.Printf("Error caching village data to Redis: %v\n", err) - } - - return villageDTO, nil + return villageDTOs, total, nil } diff --git a/model/wilayahindonesia_model.go b/model/wilayahindonesia_model.go index f8b793d..de53fb4 100644 --- a/model/wilayahindonesia_model.go +++ b/model/wilayahindonesia_model.go @@ -1,34 +1,30 @@ package model type Province struct { - ID string `gorm:"primaryKey;type:varchar(255);not null" json:"id"` - Name string `gorm:"type:varchar(255);not null" json:"name"` - + ID string `gorm:"primaryKey;type:varchar(255);not null" json:"id"` + Name string `gorm:"type:varchar(255);not null" json:"name"` Regencies []Regency `gorm:"foreignKey:ProvinceID" json:"regencies"` } type Regency struct { - ID string `gorm:"primaryKey;type:varchar(255);not null" json:"id"` - ProvinceID string `gorm:"type:varchar(255);not null" json:"province_id"` - Name string `gorm:"type:varchar(255);not null" json:"name"` - - Province Province `gorm:"foreignKey:ProvinceID" json:"province"` - Districts []District `gorm:"foreignKey:RegencyID" json:"districts"` + ID string `gorm:"primaryKey;type:varchar(255);not null" json:"id"` + ProvinceID string `gorm:"type:varchar(255);not null" json:"province_id"` + Name string `gorm:"type:varchar(255);not null" json:"name"` + Province Province `gorm:"foreignKey:ProvinceID" json:"province"` + Districts []District `gorm:"foreignKey:RegencyID" json:"districts"` } type District struct { - ID string `gorm:"primaryKey;type:varchar(255);not null" json:"id"` - RegencyID string `gorm:"type:varchar(255);not null" json:"regency_id"` - Name string `gorm:"type:varchar(255);not null" json:"name"` - - Regency Regency `gorm:"foreignKey:RegencyID" json:"regency"` - Villages []Village `gorm:"foreignKey:DistrictID" json:"villages"` + ID string `gorm:"primaryKey;type:varchar(255);not null" json:"id"` + RegencyID string `gorm:"type:varchar(255);not null" json:"regency_id"` + Name string `gorm:"type:varchar(255);not null" json:"name"` + Regency Regency `gorm:"foreignKey:RegencyID" json:"regency"` + Villages []Village `gorm:"foreignKey:DistrictID" json:"villages"` } type Village struct { - ID string `gorm:"primaryKey;type:varchar(255);not null" json:"id"` - DistrictID string `gorm:"type:varchar(255);not null" json:"district_id"` - Name string `gorm:"type:varchar(255);not null" json:"name"` - - District District `gorm:"foreignKey:DistrictID" json:"district"` + ID string `gorm:"primaryKey;type:varchar(255);not null" json:"id"` + DistrictID string `gorm:"type:varchar(255);not null" json:"district_id"` + Name string `gorm:"type:varchar(255);not null" json:"name"` + District District `gorm:"foreignKey:DistrictID" json:"district"` } diff --git a/presentation/wilayahindonesia_route.go b/presentation/wilayahindonesia_route.go index 6e36b80..c746042 100644 --- a/presentation/wilayahindonesia_route.go +++ b/presentation/wilayahindonesia_route.go @@ -18,7 +18,7 @@ func WilayahRouter(api fiber.Router) { wilayahAPI := api.Group("/wilayah-indonesia") - wilayahAPI.Get("/provinces", middleware.AuthMiddleware, wilayahHandler.GetAllProvinces) + wilayahAPI.Get("/provinces", middleware.AuthMiddleware, wilayahHandler.GetProvinces) wilayahAPI.Get("/provinces/:id", middleware.AuthMiddleware, wilayahHandler.GetProvinceByID) wilayahAPI.Get("/regencies", middleware.AuthMiddleware, wilayahHandler.GetAllRegencies) @@ -28,7 +28,6 @@ func WilayahRouter(api fiber.Router) { wilayahAPI.Get("/districts/:id", middleware.AuthMiddleware, wilayahHandler.GetDistrictByID) wilayahAPI.Get("/villages", middleware.AuthMiddleware, wilayahHandler.GetAllVillages) - wilayahAPI.Get("/villages/:id", middleware.AuthMiddleware, wilayahHandler.GetVillageByID) api.Post("/import/data-wilayah-indonesia", middleware.AuthMiddleware, middleware.RoleMiddleware(utils.RoleAdministrator), wilayahHandler.ImportWilayahData) }