MIF_E31222379_BE/internal/wilayahindo/wilayahindo_service.go

456 lines
13 KiB
Go

package wilayahindo
import (
"context"
"fmt"
"time"
"rijig/dto"
"rijig/model"
"rijig/utils"
)
type WilayahIndonesiaService interface {
ImportDataFromCSV(ctx context.Context) error
GetAllProvinces(ctx context.Context, page, limit int) ([]dto.ProvinceResponseDTO, int, error)
GetProvinceByID(ctx context.Context, id string, page, limit int) (*dto.ProvinceResponseDTO, int, error)
GetAllRegencies(ctx context.Context, page, limit int) ([]dto.RegencyResponseDTO, int, error)
GetRegencyByID(ctx context.Context, id string, page, limit int) (*dto.RegencyResponseDTO, int, error)
GetAllDistricts(ctx context.Context, page, limit int) ([]dto.DistrictResponseDTO, int, error)
GetDistrictByID(ctx context.Context, id string, page, limit int) (*dto.DistrictResponseDTO, int, error)
GetAllVillages(ctx context.Context, page, limit int) ([]dto.VillageResponseDTO, int, error)
GetVillageByID(ctx context.Context, id string) (*dto.VillageResponseDTO, error)
}
type wilayahIndonesiaService struct {
WilayahRepo WilayahIndonesiaRepository
}
func NewWilayahIndonesiaService(wilayahRepo WilayahIndonesiaRepository) WilayahIndonesiaService {
return &wilayahIndonesiaService{WilayahRepo: wilayahRepo}
}
func (s *wilayahIndonesiaService) ImportDataFromCSV(ctx context.Context) error {
provinces, err := utils.ReadCSV("public/document/provinces.csv")
if err != nil {
return fmt.Errorf("failed to read provinces CSV: %w", err)
}
var provinceList []model.Province
for _, record := range provinces[1:] {
if len(record) >= 2 {
province := model.Province{
ID: record[0],
Name: record[1],
}
provinceList = append(provinceList, province)
}
}
if err := s.WilayahRepo.ImportProvinces(ctx, provinceList); err != nil {
return fmt.Errorf("failed to import provinces: %w", err)
}
regencies, err := utils.ReadCSV("public/document/regencies.csv")
if err != nil {
return fmt.Errorf("failed to read regencies CSV: %w", err)
}
var regencyList []model.Regency
for _, record := range regencies[1:] {
if len(record) >= 3 {
regency := model.Regency{
ID: record[0],
ProvinceID: record[1],
Name: record[2],
}
regencyList = append(regencyList, regency)
}
}
if err := s.WilayahRepo.ImportRegencies(ctx, regencyList); err != nil {
return fmt.Errorf("failed to import regencies: %w", err)
}
districts, err := utils.ReadCSV("public/document/districts.csv")
if err != nil {
return fmt.Errorf("failed to read districts CSV: %w", err)
}
var districtList []model.District
for _, record := range districts[1:] {
if len(record) >= 3 {
district := model.District{
ID: record[0],
RegencyID: record[1],
Name: record[2],
}
districtList = append(districtList, district)
}
}
if err := s.WilayahRepo.ImportDistricts(ctx, districtList); err != nil {
return fmt.Errorf("failed to import districts: %w", err)
}
villages, err := utils.ReadCSV("public/document/villages.csv")
if err != nil {
return fmt.Errorf("failed to read villages CSV: %w", err)
}
var villageList []model.Village
for _, record := range villages[1:] {
if len(record) >= 3 {
village := model.Village{
ID: record[0],
DistrictID: record[1],
Name: record[2],
}
villageList = append(villageList, village)
}
}
if err := s.WilayahRepo.ImportVillages(ctx, villageList); err != nil {
return fmt.Errorf("failed to import villages: %w", err)
}
return nil
}
func (s *wilayahIndonesiaService) GetAllProvinces(ctx context.Context, page, limit int) ([]dto.ProvinceResponseDTO, int, error) {
cacheKey := fmt.Sprintf("provinces_page:%d_limit:%d", page, limit)
var cachedResponse struct {
Data []dto.ProvinceResponseDTO `json:"data"`
Total int `json:"total"`
}
if err := utils.GetCache(cacheKey, &cachedResponse); err == nil {
return cachedResponse.Data, cachedResponse.Total, nil
}
provinces, total, err := s.WilayahRepo.FindAllProvinces(ctx, page, limit)
if err != nil {
return nil, 0, fmt.Errorf("failed to fetch provinces: %w", err)
}
provinceDTOs := make([]dto.ProvinceResponseDTO, len(provinces))
for i, province := range provinces {
provinceDTOs[i] = dto.ProvinceResponseDTO{
ID: province.ID,
Name: province.Name,
}
}
cacheData := struct {
Data []dto.ProvinceResponseDTO `json:"data"`
Total int `json:"total"`
}{
Data: provinceDTOs,
Total: total,
}
if err := utils.SetCache(cacheKey, cacheData, 24*time.Hour); err != nil {
fmt.Printf("Error caching provinces data: %v\n", err)
}
return provinceDTOs, total, nil
}
func (s *wilayahIndonesiaService) GetProvinceByID(ctx context.Context, id string, page, limit int) (*dto.ProvinceResponseDTO, int, error) {
cacheKey := fmt.Sprintf("province:%s_page:%d_limit:%d", id, page, limit)
var cachedResponse struct {
Data dto.ProvinceResponseDTO `json:"data"`
TotalRegencies int `json:"total_regencies"`
}
if err := utils.GetCache(cacheKey, &cachedResponse); err == nil {
return &cachedResponse.Data, cachedResponse.TotalRegencies, nil
}
province, totalRegencies, err := s.WilayahRepo.FindProvinceByID(ctx, id, page, limit)
if err != nil {
return nil, 0, err
}
provinceDTO := dto.ProvinceResponseDTO{
ID: province.ID,
Name: province.Name,
}
regencyDTOs := make([]dto.RegencyResponseDTO, len(province.Regencies))
for i, regency := range province.Regencies {
regencyDTOs[i] = dto.RegencyResponseDTO{
ID: regency.ID,
ProvinceID: regency.ProvinceID,
Name: regency.Name,
}
}
provinceDTO.Regencies = regencyDTOs
cacheData := struct {
Data dto.ProvinceResponseDTO `json:"data"`
TotalRegencies int `json:"total_regencies"`
}{
Data: provinceDTO,
TotalRegencies: totalRegencies,
}
if err := utils.SetCache(cacheKey, cacheData, 24*time.Hour); err != nil {
fmt.Printf("Error caching province data: %v\n", err)
}
return &provinceDTO, totalRegencies, nil
}
func (s *wilayahIndonesiaService) GetAllRegencies(ctx context.Context, page, limit int) ([]dto.RegencyResponseDTO, int, error) {
cacheKey := fmt.Sprintf("regencies_page:%d_limit:%d", page, limit)
var cachedResponse struct {
Data []dto.RegencyResponseDTO `json:"data"`
Total int `json:"total"`
}
if err := utils.GetCache(cacheKey, &cachedResponse); err == nil {
return cachedResponse.Data, cachedResponse.Total, nil
}
regencies, total, err := s.WilayahRepo.FindAllRegencies(ctx, page, limit)
if err != nil {
return nil, 0, fmt.Errorf("failed to fetch regencies: %w", err)
}
regencyDTOs := make([]dto.RegencyResponseDTO, len(regencies))
for i, regency := range regencies {
regencyDTOs[i] = dto.RegencyResponseDTO{
ID: regency.ID,
ProvinceID: regency.ProvinceID,
Name: regency.Name,
}
}
cacheData := struct {
Data []dto.RegencyResponseDTO `json:"data"`
Total int `json:"total"`
}{
Data: regencyDTOs,
Total: total,
}
if err := utils.SetCache(cacheKey, cacheData, 24*time.Hour); err != nil {
fmt.Printf("Error caching regencies data: %v\n", err)
}
return regencyDTOs, total, nil
}
func (s *wilayahIndonesiaService) GetRegencyByID(ctx context.Context, id string, page, limit int) (*dto.RegencyResponseDTO, int, error) {
cacheKey := fmt.Sprintf("regency:%s_page:%d_limit:%d", id, page, limit)
var cachedResponse struct {
Data dto.RegencyResponseDTO `json:"data"`
TotalDistricts int `json:"total_districts"`
}
if err := utils.GetCache(cacheKey, &cachedResponse); err == nil {
return &cachedResponse.Data, cachedResponse.TotalDistricts, nil
}
regency, totalDistricts, err := s.WilayahRepo.FindRegencyByID(ctx, id, page, limit)
if err != nil {
return nil, 0, err
}
regencyDTO := dto.RegencyResponseDTO{
ID: regency.ID,
ProvinceID: regency.ProvinceID,
Name: regency.Name,
}
districtDTOs := make([]dto.DistrictResponseDTO, len(regency.Districts))
for i, district := range regency.Districts {
districtDTOs[i] = dto.DistrictResponseDTO{
ID: district.ID,
RegencyID: district.RegencyID,
Name: district.Name,
}
}
regencyDTO.Districts = districtDTOs
cacheData := struct {
Data dto.RegencyResponseDTO `json:"data"`
TotalDistricts int `json:"total_districts"`
}{
Data: regencyDTO,
TotalDistricts: totalDistricts,
}
if err := utils.SetCache(cacheKey, cacheData, 24*time.Hour); err != nil {
fmt.Printf("Error caching regency data: %v\n", err)
}
return &regencyDTO, totalDistricts, nil
}
func (s *wilayahIndonesiaService) GetAllDistricts(ctx context.Context, page, limit int) ([]dto.DistrictResponseDTO, int, error) {
cacheKey := fmt.Sprintf("districts_page:%d_limit:%d", page, limit)
var cachedResponse struct {
Data []dto.DistrictResponseDTO `json:"data"`
Total int `json:"total"`
}
if err := utils.GetCache(cacheKey, &cachedResponse); err == nil {
return cachedResponse.Data, cachedResponse.Total, nil
}
districts, total, err := s.WilayahRepo.FindAllDistricts(ctx, page, limit)
if err != nil {
return nil, 0, fmt.Errorf("failed to fetch districts: %w", err)
}
districtDTOs := make([]dto.DistrictResponseDTO, len(districts))
for i, district := range districts {
districtDTOs[i] = dto.DistrictResponseDTO{
ID: district.ID,
RegencyID: district.RegencyID,
Name: district.Name,
}
}
cacheData := struct {
Data []dto.DistrictResponseDTO `json:"data"`
Total int `json:"total"`
}{
Data: districtDTOs,
Total: total,
}
if err := utils.SetCache(cacheKey, cacheData, 24*time.Hour); err != nil {
fmt.Printf("Error caching districts data: %v\n", err)
}
return districtDTOs, total, nil
}
func (s *wilayahIndonesiaService) GetDistrictByID(ctx context.Context, id string, page, limit int) (*dto.DistrictResponseDTO, int, error) {
cacheKey := fmt.Sprintf("district:%s_page:%d_limit:%d", id, page, limit)
var cachedResponse struct {
Data dto.DistrictResponseDTO `json:"data"`
TotalVillages int `json:"total_villages"`
}
if err := utils.GetCache(cacheKey, &cachedResponse); err == nil {
return &cachedResponse.Data, cachedResponse.TotalVillages, nil
}
district, totalVillages, err := s.WilayahRepo.FindDistrictByID(ctx, id, page, limit)
if err != nil {
return nil, 0, err
}
districtDTO := dto.DistrictResponseDTO{
ID: district.ID,
RegencyID: district.RegencyID,
Name: district.Name,
}
villageDTOs := make([]dto.VillageResponseDTO, len(district.Villages))
for i, village := range district.Villages {
villageDTOs[i] = dto.VillageResponseDTO{
ID: village.ID,
DistrictID: village.DistrictID,
Name: village.Name,
}
}
districtDTO.Villages = villageDTOs
cacheData := struct {
Data dto.DistrictResponseDTO `json:"data"`
TotalVillages int `json:"total_villages"`
}{
Data: districtDTO,
TotalVillages: totalVillages,
}
if err := utils.SetCache(cacheKey, cacheData, 24*time.Hour); err != nil {
fmt.Printf("Error caching district data: %v\n", err)
}
return &districtDTO, totalVillages, nil
}
func (s *wilayahIndonesiaService) GetAllVillages(ctx context.Context, page, limit int) ([]dto.VillageResponseDTO, int, error) {
cacheKey := fmt.Sprintf("villages_page:%d_limit:%d", page, limit)
var cachedResponse struct {
Data []dto.VillageResponseDTO `json:"data"`
Total int `json:"total"`
}
if err := utils.GetCache(cacheKey, &cachedResponse); err == nil {
return cachedResponse.Data, cachedResponse.Total, nil
}
villages, total, err := s.WilayahRepo.FindAllVillages(ctx, page, limit)
if err != nil {
return nil, 0, fmt.Errorf("failed to fetch villages: %w", err)
}
villageDTOs := make([]dto.VillageResponseDTO, len(villages))
for i, village := range villages {
villageDTOs[i] = dto.VillageResponseDTO{
ID: village.ID,
DistrictID: village.DistrictID,
Name: village.Name,
}
}
cacheData := struct {
Data []dto.VillageResponseDTO `json:"data"`
Total int `json:"total"`
}{
Data: villageDTOs,
Total: total,
}
if err := utils.SetCache(cacheKey, cacheData, 24*time.Hour); err != nil {
fmt.Printf("Error caching villages data: %v\n", err)
}
return villageDTOs, total, nil
}
func (s *wilayahIndonesiaService) GetVillageByID(ctx context.Context, id string) (*dto.VillageResponseDTO, error) {
cacheKey := fmt.Sprintf("village:%s", id)
var cachedResponse dto.VillageResponseDTO
if err := utils.GetCache(cacheKey, &cachedResponse); err == nil {
return &cachedResponse, nil
}
village, err := s.WilayahRepo.FindVillageByID(ctx, id)
if err != nil {
return nil, fmt.Errorf("village not found: %w", err)
}
villageResponse := &dto.VillageResponseDTO{
ID: village.ID,
DistrictID: village.DistrictID,
Name: village.Name,
}
if err := utils.SetCache(cacheKey, villageResponse, 24*time.Hour); err != nil {
fmt.Printf("Error caching village data: %v\n", err)
}
return villageResponse, nil
}