feat: add feature wilayah indonesia api

This commit is contained in:
pahmiudahgede 2025-02-06 14:01:23 +07:00
parent 35d51b99d0
commit 1c856773a1
13 changed files with 92533 additions and 88297 deletions

View File

@ -31,9 +31,18 @@ func ConnectDatabase() {
log.Println("Database connected successfully!") log.Println("Database connected successfully!")
err = DB.AutoMigrate( err = DB.AutoMigrate(
// ==wilayah indonesia==
&model.Province{},
&model.Regency{},
&model.District{},
&model.Village{},
// ==wilayah indonesia==
// ==main feature==
&model.User{}, &model.User{},
&model.Role{}, &model.Role{},
&model.UserPin{}, &model.UserPin{},
// ==main feature==
) )
if err != nil { if err != nil {
log.Fatalf("Error performing auto-migration: %v", err) log.Fatalf("Error performing auto-migration: %v", err)

View File

@ -0,0 +1,27 @@
package dto
type ProvinceResponseDTO struct {
ID string `json:"id"`
Name string `json:"name"`
Regencies []RegencyResponseDTO `json:"regencies,omitempty"`
}
type RegencyResponseDTO struct {
ID string `json:"id"`
ProvinceID string `json:"province_id"`
Name string `json:"name"`
Districts []DistrictResponseDTO `json:"districts,omitempty"`
}
type DistrictResponseDTO struct {
ID string `json:"id"`
RegencyID string `json:"regency_id"`
Name string `json:"name"`
Villages []VillageResponseDTO `json:"villages,omitempty"`
}
type VillageResponseDTO struct {
ID string `json:"id"`
DistrictID string `json:"district_id"`
Name string `json:"name"`
}

View File

@ -0,0 +1,148 @@
package handler
import (
"fmt"
"strconv"
"github.com/gofiber/fiber/v2"
"github.com/pahmiudahgede/senggoldong/internal/services"
"github.com/pahmiudahgede/senggoldong/utils"
)
type WilayahIndonesiaHandler struct {
WilayahService services.WilayahIndonesiaService
}
func NewWilayahImportHandler(wilayahService services.WilayahIndonesiaService) *WilayahIndonesiaHandler {
return &WilayahIndonesiaHandler{WilayahService: wilayahService}
}
func (h *WilayahIndonesiaHandler) ImportWilayahData(c *fiber.Ctx) error {
err := h.WilayahService.ImportDataFromCSV()
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, err.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"))
if err != nil {
page = 1
}
limit, err := strconv.Atoi(c.Query("limit", "10"))
if err != nil {
limit = 10
}
provinces, err := h.WilayahService.GetAllProvinces(page, limit)
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, fmt.Sprintf("Failed to fetch provinces: %v", err))
}
return utils.PaginatedResponse(c, provinces, page, limit, len(provinces), "Provinces fetched successfully")
}
func (h *WilayahIndonesiaHandler) GetProvinceByID(c *fiber.Ctx) error {
provinceID := c.Params("id")
province, err := h.WilayahService.GetProvinceByID(provinceID)
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusNotFound, fmt.Sprintf("Province not found: %v", err))
}
return utils.LogResponse(c, province, "Province fetched successfully")
}
func (h *WilayahIndonesiaHandler) GetAllRegencies(c *fiber.Ctx) error {
page, err := strconv.Atoi(c.Query("page", "1"))
if err != nil {
page = 1
}
limit, err := strconv.Atoi(c.Query("limit", "10"))
if err != nil {
limit = 10
}
regencies, err := h.WilayahService.GetAllRegencies(page, limit)
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, fmt.Sprintf("Failed to fetch regencies: %v", err))
}
return utils.PaginatedResponse(c, regencies, page, limit, len(regencies), "Regencies fetched successfully")
}
func (h *WilayahIndonesiaHandler) GetRegencyByID(c *fiber.Ctx) error {
regencyID := c.Params("id")
regency, err := h.WilayahService.GetRegencyByID(regencyID)
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusNotFound, fmt.Sprintf("Regency not found: %v", err))
}
return utils.LogResponse(c, regency, "Regency fetched successfully")
}
func (h *WilayahIndonesiaHandler) GetAllDistricts(c *fiber.Ctx) error {
page, err := strconv.Atoi(c.Query("page", "1"))
if err != nil {
page = 1
}
limit, err := strconv.Atoi(c.Query("limit", "10"))
if err != nil {
limit = 10
}
districts, err := h.WilayahService.GetAllDistricts(page, limit)
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, fmt.Sprintf("Failed to fetch districts: %v", err))
}
return utils.PaginatedResponse(c, districts, page, limit, len(districts), "Districts fetched successfully")
}
func (h *WilayahIndonesiaHandler) GetDistrictByID(c *fiber.Ctx) error {
districtID := c.Params("id")
district, err := h.WilayahService.GetDistrictByID(districtID)
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusNotFound, fmt.Sprintf("District not found: %v", err))
}
return utils.LogResponse(c, district, "District fetched successfully")
}
func (h *WilayahIndonesiaHandler) GetAllVillages(c *fiber.Ctx) error {
page, err := strconv.Atoi(c.Query("page", "1"))
if err != nil {
page = 1
}
limit, err := strconv.Atoi(c.Query("limit", "10"))
if err != nil {
limit = 10
}
villages, err := h.WilayahService.GetAllVillages(page, limit)
if err != nil {
return utils.GenericErrorResponse(c, fiber.StatusInternalServerError, fmt.Sprintf("Failed to fetch villages: %v", err))
}
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")
}

View File

@ -0,0 +1,194 @@
package repositories
import (
"github.com/pahmiudahgede/senggoldong/model"
"gorm.io/gorm"
)
type WilayahIndonesiaRepository interface {
ImportProvinces(provinces []model.Province) error
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)
FindAllRegencies(page, limit int) ([]model.Regency, int, error)
FindRegencyByID(id string) (*model.Regency, error)
FindAllDistricts(page, limit int) ([]model.District, int, error)
FindDistrictByID(id string) (*model.District, error)
FindAllVillages(page, limit int) ([]model.Village, int, error)
FindVillageByID(id string) (*model.Village, error)
}
type wilayahIndonesiaRepository struct {
DB *gorm.DB
}
func NewWilayahIndonesiaRepository(db *gorm.DB) WilayahIndonesiaRepository {
return &wilayahIndonesiaRepository{DB: db}
}
func (r *wilayahIndonesiaRepository) ImportProvinces(provinces []model.Province) error {
for _, province := range provinces {
if err := r.DB.Create(&province).Error; err != nil {
return err
}
}
return nil
}
func (r *wilayahIndonesiaRepository) ImportRegencies(regencies []model.Regency) error {
for _, regency := range regencies {
if err := r.DB.Create(&regency).Error; err != nil {
return err
}
}
return nil
}
func (r *wilayahIndonesiaRepository) ImportDistricts(districts []model.District) error {
for _, district := range districts {
if err := r.DB.Create(&district).Error; err != nil {
return err
}
}
return nil
}
func (r *wilayahIndonesiaRepository) ImportVillages(villages []model.Village) error {
for _, village := range villages {
if err := r.DB.Create(&village).Error; err != nil {
return err
}
}
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
}
return provinces, int(total), nil
}
// FindProvinceByID
func (r *wilayahIndonesiaRepository) FindProvinceByID(id string) (*model.Province, error) {
var province model.Province
err := r.DB.Preload("Regencies").Where("id = ?", id).First(&province).Error
if err != nil {
return nil, err
}
return &province, 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(&regencies).Error
if err != nil {
return nil, 0, err
}
return regencies, int(total), nil
}
// FindRegencyByID
func (r *wilayahIndonesiaRepository) FindRegencyByID(id string) (*model.Regency, error) {
var regency model.Regency
err := r.DB.Preload("Districts").Where("id = ?", id).First(&regency).Error
if err != nil {
return nil, err
}
return &regency, nil
}
// FindAllDistricts with Pagination
func (r *wilayahIndonesiaRepository) FindAllDistricts(page, limit int) ([]model.District, int, error) {
var districts []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 err != nil {
return nil, 0, err
}
return districts, int(total), 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 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
}
return villages, 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
}

View File

@ -0,0 +1,487 @@
package services
import (
"fmt"
"time"
"github.com/pahmiudahgede/senggoldong/dto"
"github.com/pahmiudahgede/senggoldong/internal/repositories"
"github.com/pahmiudahgede/senggoldong/model"
"github.com/pahmiudahgede/senggoldong/utils"
)
type WilayahIndonesiaService interface {
ImportDataFromCSV() error
GetAllProvinces(page, limit int) ([]dto.ProvinceResponseDTO, error)
GetProvinceByID(id string) (*dto.ProvinceResponseDTO, error)
GetAllRegencies(page, limit int) ([]dto.RegencyResponseDTO, error)
GetRegencyByID(id string) (*dto.RegencyResponseDTO, error)
GetAllDistricts(page, limit int) ([]dto.DistrictResponseDTO, error)
GetDistrictByID(id string) (*dto.DistrictResponseDTO, error)
GetAllVillages(page, limit int) ([]dto.VillageResponseDTO, error)
GetVillageByID(id string) (*dto.VillageResponseDTO, error)
}
type wilayahIndonesiaService struct {
WilayahRepo repositories.WilayahIndonesiaRepository
}
func NewWilayahIndonesiaService(wilayahRepo repositories.WilayahIndonesiaRepository) WilayahIndonesiaService {
return &wilayahIndonesiaService{WilayahRepo: wilayahRepo}
}
func (s *wilayahIndonesiaService) ImportDataFromCSV() error {
provinces, err := utils.ReadCSV("public/document/provinces.csv")
if err != nil {
return fmt.Errorf("failed to read provinces CSV: %v", err)
}
var provinceList []model.Province
for _, record := range provinces[1:] {
province := model.Province{
ID: record[0],
Name: record[1],
}
provinceList = append(provinceList, province)
}
if err := s.WilayahRepo.ImportProvinces(provinceList); err != nil {
return fmt.Errorf("failed to import provinces: %v", err)
}
regencies, err := utils.ReadCSV("public/document/regencies.csv")
if err != nil {
return fmt.Errorf("failed to read regencies CSV: %v", err)
}
var regencyList []model.Regency
for _, record := range regencies[1:] {
regency := model.Regency{
ID: record[0],
ProvinceID: record[1],
Name: record[2],
}
regencyList = append(regencyList, regency)
}
if err := s.WilayahRepo.ImportRegencies(regencyList); err != nil {
return fmt.Errorf("failed to import regencies: %v", err)
}
districts, err := utils.ReadCSV("public/document/districts.csv")
if err != nil {
return fmt.Errorf("failed to read districts CSV: %v", err)
}
var districtList []model.District
for _, record := range districts[1:] {
district := model.District{
ID: record[0],
RegencyID: record[1],
Name: record[2],
}
districtList = append(districtList, district)
}
if err := s.WilayahRepo.ImportDistricts(districtList); err != nil {
return fmt.Errorf("failed to import districts: %v", err)
}
villages, err := utils.ReadCSV("public/document/villages.csv")
if err != nil {
return fmt.Errorf("failed to read villages CSV: %v", err)
}
var villageList []model.Village
for _, record := range villages[1:] {
village := model.Village{
ID: record[0],
DistrictID: record[1],
Name: record[2],
}
villageList = append(villageList, village)
}
if err := s.WilayahRepo.ImportVillages(villageList); err != nil {
return fmt.Errorf("failed to import villages: %v", err)
}
return nil
}
func (s *wilayahIndonesiaService) GetAllProvinces(page, limit int) ([]dto.ProvinceResponseDTO, error) {
cacheKey := fmt.Sprintf("provinces_page_%d_limit_%d", page, limit)
cachedData, err := utils.GetJSONData(cacheKey)
if err == nil && cachedData != nil {
var provinces []dto.ProvinceResponseDTO
if data, ok := cachedData["data"].([]interface{}); ok {
for _, item := range data {
province, ok := item.(map[string]interface{})
if ok {
provinces = append(provinces, dto.ProvinceResponseDTO{
ID: province["id"].(string),
Name: province["name"].(string),
})
}
}
return provinces, nil
}
}
provinces, total, err := s.WilayahRepo.FindAllProvinces(page, limit)
if err != nil {
return nil, fmt.Errorf("failed to fetch provinces: %v", err)
}
var provinceDTOs []dto.ProvinceResponseDTO
for _, province := range provinces {
provinceDTOs = append(provinceDTOs, dto.ProvinceResponseDTO{
ID: province.ID,
Name: province.Name,
})
}
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)
}
return provinceDTOs, nil
}
func (s *wilayahIndonesiaService) GetProvinceByID(id string) (*dto.ProvinceResponseDTO, error) {
cacheKey := fmt.Sprintf("province:%s", id)
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),
}
return &province, nil
}
}
province, err := s.WilayahRepo.FindProvinceByID(id)
if err != nil {
return nil, fmt.Errorf("failed to fetch province: %v", err)
}
provinceDTO := &dto.ProvinceResponseDTO{
ID: province.ID,
Name: province.Name,
}
regenciesDTO := []dto.RegencyResponseDTO{}
for _, regency := range province.Regencies {
regenciesDTO = append(regenciesDTO, dto.RegencyResponseDTO{
ID: regency.ID,
ProvinceID: regency.ProvinceID,
Name: regency.Name,
})
}
provinceDTO.Regencies = regenciesDTO
cacheData := map[string]interface{}{
"data": provinceDTO,
}
err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24)
if err != nil {
fmt.Printf("Error caching province data to Redis: %v\n", err)
}
return provinceDTO, nil
}
func (s *wilayahIndonesiaService) GetAllRegencies(page, limit int) ([]dto.RegencyResponseDTO, error) {
cacheKey := fmt.Sprintf("regencies_page_%d_limit_%d", page, limit)
cachedData, err := utils.GetJSONData(cacheKey)
if err == nil && cachedData != nil {
var regencies []dto.RegencyResponseDTO
if data, ok := cachedData["data"].([]interface{}); ok {
for _, item := range data {
regency, ok := item.(map[string]interface{})
if ok {
regencies = append(regencies, dto.RegencyResponseDTO{
ID: regency["id"].(string),
ProvinceID: regency["province_id"].(string),
Name: regency["name"].(string),
})
}
}
return regencies, nil
}
}
regencies, total, err := s.WilayahRepo.FindAllRegencies(page, limit)
if err != nil {
return nil, fmt.Errorf("failed to fetch regencies: %v", err)
}
var regencyDTOs []dto.RegencyResponseDTO
for _, regency := range regencies {
regencyDTOs = append(regencyDTOs, dto.RegencyResponseDTO{
ID: regency.ID,
ProvinceID: regency.ProvinceID,
Name: regency.Name,
})
}
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)
}
return regencyDTOs, nil
}
func (s *wilayahIndonesiaService) GetRegencyByID(id string) (*dto.RegencyResponseDTO, error) {
cacheKey := fmt.Sprintf("regency:%s", id)
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),
}
return &regency, nil
}
}
regency, err := s.WilayahRepo.FindRegencyByID(id)
if err != nil {
return nil, fmt.Errorf("failed to fetch regency: %v", err)
}
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,
})
}
regencyDTO.Districts = districtsDTO
cacheData := map[string]interface{}{
"data": regencyDTO,
}
err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24)
if err != nil {
fmt.Printf("Error caching regency data to Redis: %v\n", err)
}
return regencyDTO, nil
}
func (s *wilayahIndonesiaService) GetAllDistricts(page, limit int) ([]dto.DistrictResponseDTO, error) {
cacheKey := fmt.Sprintf("districts_page_%d_limit_%d", page, limit)
cachedData, err := utils.GetJSONData(cacheKey)
if err == nil && cachedData != nil {
var districts []dto.DistrictResponseDTO
if data, ok := cachedData["data"].([]interface{}); ok {
for _, item := range data {
district, ok := item.(map[string]interface{})
if ok {
districts = append(districts, dto.DistrictResponseDTO{
ID: district["id"].(string),
RegencyID: district["regency_id"].(string),
Name: district["name"].(string),
})
}
}
return districts, nil
}
}
districts, total, err := s.WilayahRepo.FindAllDistricts(page, limit)
if err != nil {
return nil, fmt.Errorf("failed to fetch districts: %v", err)
}
var districtDTOs []dto.DistrictResponseDTO
for _, district := range districts {
districtDTOs = append(districtDTOs, dto.DistrictResponseDTO{
ID: district.ID,
RegencyID: district.RegencyID,
Name: district.Name,
})
}
cacheData := map[string]interface{}{
"data": districtDTOs,
"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)
}
return districtDTOs, nil
}
func (s *wilayahIndonesiaService) GetDistrictByID(id string) (*dto.DistrictResponseDTO, error) {
cacheKey := fmt.Sprintf("district:%s", id)
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),
}
return &district, nil
}
}
district, err := s.WilayahRepo.FindDistrictByID(id)
if err != nil {
return nil, fmt.Errorf("failed to fetch district: %v", err)
}
districtDTO := &dto.DistrictResponseDTO{
ID: district.ID,
RegencyID: district.RegencyID,
Name: district.Name,
}
villagesDTO := []dto.VillageResponseDTO{}
for _, village := range district.Villages {
villagesDTO = append(villagesDTO, dto.VillageResponseDTO{
ID: village.ID,
DistrictID: village.DistrictID,
Name: village.Name,
})
}
districtDTO.Villages = villagesDTO
cacheData := map[string]interface{}{
"data": districtDTO,
}
err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24)
if err != nil {
fmt.Printf("Error caching district data to Redis: %v\n", err)
}
return districtDTO, nil
}
func (s *wilayahIndonesiaService) GetAllVillages(page, limit int) ([]dto.VillageResponseDTO, error) {
cacheKey := fmt.Sprintf("villages:%d:%d", page, limit)
cachedData, err := utils.GetJSONData(cacheKey)
if err == nil && cachedData != nil {
var villages []dto.VillageResponseDTO
if data, ok := cachedData["data"].([]interface{}); ok {
for _, item := range data {
village, ok := item.(map[string]interface{})
if ok {
villages = append(villages, dto.VillageResponseDTO{
ID: village["id"].(string),
DistrictID: village["district_id"].(string),
Name: village["name"].(string),
})
}
}
return villages, nil
}
}
villages, total, err := s.WilayahRepo.FindAllVillages(page, limit)
if err != nil {
return nil, fmt.Errorf("failed to fetch villages: %v", err)
}
var villageDTOs []dto.VillageResponseDTO
for _, village := range villages {
villageDTOs = append(villageDTOs, dto.VillageResponseDTO{
ID: village.ID,
DistrictID: village.DistrictID,
Name: village.Name,
})
}
cacheData := map[string]interface{}{
"data": villageDTOs,
"total": total,
}
err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24)
if err != nil {
fmt.Printf("Error caching village data to Redis: %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
}

View File

@ -0,0 +1,34 @@
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"`
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"`
}
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"`
}
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"`
}

View File

@ -0,0 +1,34 @@
package presentation
import (
"github.com/gofiber/fiber/v2"
"github.com/pahmiudahgede/senggoldong/config"
"github.com/pahmiudahgede/senggoldong/internal/handler"
"github.com/pahmiudahgede/senggoldong/internal/repositories"
"github.com/pahmiudahgede/senggoldong/internal/services"
"github.com/pahmiudahgede/senggoldong/middleware"
"github.com/pahmiudahgede/senggoldong/utils"
)
func WilayahRouter(api fiber.Router) {
wilayahRepo := repositories.NewWilayahIndonesiaRepository(config.DB)
wilayahService := services.NewWilayahIndonesiaService(wilayahRepo)
wilayahHandler := handler.NewWilayahImportHandler(wilayahService)
wilayahAPI := api.Group("/wilayah-indonesia")
wilayahAPI.Get("/provinces", middleware.AuthMiddleware, wilayahHandler.GetAllProvinces)
wilayahAPI.Get("/provinces/:id", middleware.AuthMiddleware, wilayahHandler.GetProvinceByID)
wilayahAPI.Get("/regencies", middleware.AuthMiddleware, wilayahHandler.GetAllRegencies)
wilayahAPI.Get("/regencies/:id", middleware.AuthMiddleware, wilayahHandler.GetRegencyByID)
wilayahAPI.Get("/districts", middleware.AuthMiddleware, wilayahHandler.GetAllDistricts)
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)
}

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +1,38 @@
11,ACEH id;name
12,SUMATERA UTARA 11;ACEH
13,SUMATERA BARAT 12;"SUMATERA UTARA"
14,RIAU 13;"SUMATERA BARAT"
15,JAMBI 14;RIAU
16,SUMATERA SELATAN 15;JAMBI
17,BENGKULU 16;"SUMATERA SELATAN"
18,LAMPUNG 17;BENGKULU
19,KEPULAUAN BANGKA BELITUNG 18;LAMPUNG
21,KEPULAUAN RIAU 19;"KEPULAUAN BANGKA BELITUNG"
31,DKI JAKARTA 21;"KEPULAUAN RIAU"
32,JAWA BARAT 31;"DKI JAKARTA"
33,JAWA TENGAH 32;"JAWA BARAT"
34,DI YOGYAKARTA 33;"JAWA TENGAH"
35,JAWA TIMUR 34;"DAERAH ISTIMEWA YOGYAKARTA"
36,BANTEN 35;"JAWA TIMUR"
51,BALI 36;BANTEN
52,NUSA TENGGARA BARAT 51;BALI
53,NUSA TENGGARA TIMUR 52;"NUSA TENGGARA BARAT"
61,KALIMANTAN BARAT 53;"NUSA TENGGARA TIMUR"
62,KALIMANTAN TENGAH 61;"KALIMANTAN BARAT"
63,KALIMANTAN SELATAN 62;"KALIMANTAN TENGAH"
64,KALIMANTAN TIMUR 63;"KALIMANTAN SELATAN"
65,KALIMANTAN UTARA 64;"KALIMANTAN TIMUR"
71,SULAWESI UTARA 65;"KALIMANTAN UTARA"
72,SULAWESI TENGAH 71;"SULAWESI UTARA"
73,SULAWESI SELATAN 72;"SULAWESI TENGAH"
74,SULAWESI TENGGARA 73;"SULAWESI SELATAN"
75,GORONTALO 74;"SULAWESI TENGGARA"
76,SULAWESI BARAT 75;GORONTALO
81,MALUKU 76;"SULAWESI BARAT"
82,MALUKU UTARA 81;MALUKU
91,PAPUA BARAT 82;"MALUKU UTARA"
94,PAPUA 91;PAPUA
92;"PAPUA BARAT"
93;"PAPUA SELATAN"
94;"PAPUA TENGAH"
95;"PAPUA PEGUNUNGAN"

1 11 id ACEH name
2 12 11 SUMATERA UTARA ACEH
3 13 12 SUMATERA BARAT SUMATERA UTARA
4 14 13 RIAU SUMATERA BARAT
5 15 14 JAMBI RIAU
6 16 15 SUMATERA SELATAN JAMBI
7 17 16 BENGKULU SUMATERA SELATAN
8 18 17 LAMPUNG BENGKULU
9 19 18 KEPULAUAN BANGKA BELITUNG LAMPUNG
10 21 19 KEPULAUAN RIAU KEPULAUAN BANGKA BELITUNG
11 31 21 DKI JAKARTA KEPULAUAN RIAU
12 32 31 JAWA BARAT DKI JAKARTA
13 33 32 JAWA TENGAH JAWA BARAT
14 34 33 DI YOGYAKARTA JAWA TENGAH
15 35 34 JAWA TIMUR DAERAH ISTIMEWA YOGYAKARTA
16 36 35 BANTEN JAWA TIMUR
17 51 36 BALI BANTEN
18 52 51 NUSA TENGGARA BARAT BALI
19 53 52 NUSA TENGGARA TIMUR NUSA TENGGARA BARAT
20 61 53 KALIMANTAN BARAT NUSA TENGGARA TIMUR
21 62 61 KALIMANTAN TENGAH KALIMANTAN BARAT
22 63 62 KALIMANTAN SELATAN KALIMANTAN TENGAH
23 64 63 KALIMANTAN TIMUR KALIMANTAN SELATAN
24 65 64 KALIMANTAN UTARA KALIMANTAN TIMUR
25 71 65 SULAWESI UTARA KALIMANTAN UTARA
26 72 71 SULAWESI TENGAH SULAWESI UTARA
27 73 72 SULAWESI SELATAN SULAWESI TENGAH
28 74 73 SULAWESI TENGGARA SULAWESI SELATAN
29 75 74 GORONTALO SULAWESI TENGGARA
30 76 75 SULAWESI BARAT GORONTALO
31 81 76 MALUKU SULAWESI BARAT
32 82 81 MALUKU UTARA MALUKU
33 91 82 PAPUA BARAT MALUKU UTARA
34 94 91 PAPUA PAPUA
35 92 PAPUA BARAT
36 93 PAPUA SELATAN
37 94 PAPUA TENGAH
38 95 PAPUA PEGUNUNGAN

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -13,4 +13,5 @@ func SetupRoutes(app *fiber.App) {
presentation.UserProfileRouter(api) presentation.UserProfileRouter(api)
presentation.UserPinRouter(api) presentation.UserPinRouter(api)
presentation.RoleRouter(api) presentation.RoleRouter(api)
presentation.WilayahRouter(api)
} }

View File

@ -13,9 +13,15 @@ func ReadCSV(filePath string) ([][]string, error) {
defer file.Close() defer file.Close()
reader := csv.NewReader(file) reader := csv.NewReader(file)
reader.Comma = ';'
reader.LazyQuotes = true
reader.FieldsPerRecord = -1
records, err := reader.ReadAll() records, err := reader.ReadAll()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return records, nil return records, nil
} }