Files
2025-05-15 13:45:45 +07:00

572 lines
16 KiB
Go

package mongo
import (
Mongomaster "api-poliklinik/pkg/models/mongo/master/masteraddress"
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
"strings"
"time"
)
func (s *DatabaseService) InsertState(req Mongomaster.State) error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
_, err := s.DBMongo.Collection("state").InsertOne(ctx, req)
if err != nil {
log.Println(err)
return err
}
return nil
}
func (s *DatabaseService) InsertCity(req Mongomaster.City) error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
_, err := s.DBMongo.Collection("city").InsertOne(ctx, req)
if err != nil {
log.Println(err)
return err
}
return nil
}
func (s *DatabaseService) InsertDistrict(req Mongomaster.District) error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
_, err := s.DBMongo.Collection("district").InsertOne(ctx, req)
if err != nil {
log.Println(err)
return err
}
return nil
}
func (s *DatabaseService) InsertVillage(req Mongomaster.Village) error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
_, err := s.DBMongo.Collection("village").InsertOne(ctx, req)
if err != nil {
log.Println(err)
return err
}
return nil
}
func (s *DatabaseService) Getsmf() ([]*Mongomaster.Smfmongo, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
datasmf, err := s.DBMongo.Collection("smf").Find(ctx, bson.D{})
if err != nil {
log.Println(err)
}
var smf []*Mongomaster.Smfmongo
err = datasmf.All(ctx, &smf)
if err != nil {
log.Println(err)
return nil, err
}
return smf, nil
}
func (s *DatabaseService) GetICD(limit int64, skip int64) ([]*Mongomaster.Icdmongo, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
findOptions := options.Find()
findOptions.SetLimit(limit)
findOptions.SetSkip(skip)
filter := bson.M{
"status": "active",
}
dataICD, err := s.DBMongo.Collection("icd").Find(ctx, filter, findOptions)
if err != nil {
log.Println(err)
}
var ICD []*Mongomaster.Icdmongo
err = dataICD.All(ctx, &ICD)
if err != nil {
log.Println(err)
return nil, err
}
return ICD, nil
}
func (s *DatabaseService) Getdataprovinsi() ([]*Mongomaster.State, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
dataprovinsi, err := s.DBMongo.Collection("state").Find(ctx, bson.D{})
if err != nil {
log.Println(err)
}
var provinsi []*Mongomaster.State
err = dataprovinsi.All(ctx, &provinsi)
if err != nil {
log.Println(err)
return nil, err
}
return provinsi, nil
}
func (s *DatabaseService) Getdatakota() ([]*Mongomaster.City, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
datakota, err := s.DBMongo.Collection("city").Find(ctx, bson.D{})
if err != nil {
log.Println(err)
}
var kota []*Mongomaster.City
err = datakota.All(ctx, &kota)
if err != nil {
log.Println(err)
return nil, err
}
return kota, nil
}
func (s *DatabaseService) Getdatakecamatan() ([]*Mongomaster.District, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
datakecamatan, err := s.DBMongo.Collection("district").Find(ctx, bson.D{})
if err != nil {
log.Println(err)
}
var kecamatan []*Mongomaster.District
err = datakecamatan.All(ctx, &kecamatan)
if err != nil {
log.Println(err)
return nil, err
}
return kecamatan, nil
}
func (s *DatabaseService) Getdatakelurahan(name string) ([]*Mongomaster.Village, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
filter := bson.M{
"name": name,
}
datakelurahan, err := s.DBMongo.Collection("village").Find(ctx, filter)
if err != nil {
log.Println(err)
}
var kelurahan []*Mongomaster.Village
err = datakelurahan.All(ctx, &kelurahan)
if err != nil {
log.Println(err)
return nil, err
}
return kelurahan, nil
}
func (s *DatabaseService) SearchKelurahan(query string) ([]*Mongomaster.Village, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Buat regex pattern untuk pencarian case-insensitive
regex := primitive.Regex{Pattern: query, Options: "i"}
// Buat filter untuk pencarian berdasarkan nama
filter := bson.M{
"name": regex,
}
// Cari kelurahan yang cocok, batasi 10 hasil
opts := options.Find().SetLimit(10)
cursor, err := s.DBMongo.Collection("village").Find(ctx, filter, opts)
if err != nil {
log.Println(err)
return nil, err
}
// Decode hasil query ke dalam slice struct
var kelurahanList []*Mongomaster.Village
if err = cursor.All(ctx, &kelurahanList); err != nil {
log.Println(err)
return nil, err
}
return kelurahanList, nil
}
func (s *DatabaseService) GetHierarchyByKelurahan(kelurahanId string) (map[string]interface{}, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// 1. Cari data kelurahan berdasarkan identifier[0].value
filter := bson.M{
"identifier.0.value": kelurahanId,
}
log.Printf("Mencari kelurahan dengan filter: %v", filter)
var kelurahan Mongomaster.Village
err := s.DBMongo.Collection("village").FindOne(ctx, filter).Decode(&kelurahan)
if err != nil {
log.Println("Error saat mencari kelurahan:", err)
return nil, err
}
log.Printf("Kelurahan ditemukan: %s, reference kecamatan: %s", kelurahan.Name, kelurahan.District.Reference)
// 2. Ekstrak ID kecamatan dari referensi
// PENTING: Periksa format referensi yang sebenarnya
districtRef := kelurahan.District.Reference
var districtId string
// Coba berbagai format yang mungkin
if strings.HasPrefix(districtRef, "distric/") {
districtId = strings.Replace(districtRef, "distric/", "", 1)
} else if strings.HasPrefix(districtRef, "district/") {
districtId = strings.Replace(districtRef, "district/", "", 1)
} else {
// Jika format lain, ambil bagian setelah "/"
parts := strings.Split(districtRef, "/")
if len(parts) > 1 {
districtId = parts[1]
} else {
districtId = districtRef // Gunakan seluruh string jika tidak ada "/"
}
}
log.Printf("ID kecamatan yang diekstrak: %s", districtId)
// 3. Cari data kecamatan berdasarkan identifier.value
// Coba beberapa kemungkinan filter
var kecamatan Mongomaster.District
var kecamatanErr error
// Coba dengan exact match pada identifier.value
kecamatanFilter1 := bson.M{
"identifier.0.value": districtId,
}
log.Printf("Mencoba filter kecamatan 1: %v", kecamatanFilter1)
kecamatanErr = s.DBMongo.Collection("district").FindOne(ctx, kecamatanFilter1).Decode(&kecamatan)
// Jika masih error, coba dengan _id
if kecamatanErr != nil {
log.Printf("Filter 1 gagal: %v, mencoba filter 2", kecamatanErr)
kecamatanFilter2 := bson.M{
"_id": districtId,
}
kecamatanErr = s.DBMongo.Collection("district").FindOne(ctx, kecamatanFilter2).Decode(&kecamatan)
}
// Jika masih error, coba dengan regex search pada name
if kecamatanErr != nil {
log.Printf("Filter 2 gagal: %v, mencoba filter berdasarkan display name", kecamatanErr)
kecamatanFilter3 := bson.M{
"name": kelurahan.District.Display,
}
kecamatanErr = s.DBMongo.Collection("district").FindOne(ctx, kecamatanFilter3).Decode(&kecamatan)
}
// Jika semua filter gagal
if kecamatanErr != nil {
log.Println("Error saat mencari kecamatan dengan semua filter:", kecamatanErr)
// Tampilkan semua kecamatan untuk debugging
debugCursor, debugErr := s.DBMongo.Collection("district").Find(ctx, bson.M{})
if debugErr == nil {
var allDistricts []Mongomaster.District
debugErr = debugCursor.All(ctx, &allDistricts)
if debugErr == nil {
log.Printf("Daftar semua kecamatan (sampel 3): %+v", allDistricts[:min(3, len(allDistricts))])
}
}
return nil, kecamatanErr
}
log.Printf("Kecamatan ditemukan: %s, reference kota: %s", kecamatan.Name, kecamatan.City.Reference)
// 4. Ekstrak ID kota dari referensi (dengan pendekatan yang sama)
cityRef := kecamatan.City.Reference
var cityId string
if strings.HasPrefix(cityRef, "city/") {
cityId = strings.Replace(cityRef, "city/", "", 1)
} else {
parts := strings.Split(cityRef, "/")
if len(parts) > 1 {
cityId = parts[1]
} else {
cityId = cityRef
}
}
log.Printf("ID kota yang diekstrak: %s", cityId)
// 5. Cari data kota
kotaFilter := bson.M{
"identifier.0.value": cityId,
}
var kota Mongomaster.City
err = s.DBMongo.Collection("city").FindOne(ctx, kotaFilter).Decode(&kota)
if err != nil {
log.Println("Error saat mencari kota:", err)
return nil, err
}
log.Printf("Kota ditemukan: %s, reference provinsi: %s", kota.Name, kota.State.Reference)
// 6. Ekstrak ID provinsi
stateRef := kota.State.Reference
var stateId string
if strings.HasPrefix(stateRef, "provinsi/") {
stateId = strings.Replace(stateRef, "provinsi/", "", 1)
} else {
parts := strings.Split(stateRef, "/")
if len(parts) > 1 {
stateId = parts[1]
} else {
stateId = stateRef
}
}
log.Printf("ID provinsi yang diekstrak: %s", stateId)
// 7. Cari data provinsi
provinsiFilter := bson.M{
"identifier.0.value": stateId,
}
var provinsi Mongomaster.State
err = s.DBMongo.Collection("state").FindOne(ctx, provinsiFilter).Decode(&provinsi)
if err != nil {
log.Println("Error saat mencari provinsi:", err)
return nil, err
}
log.Printf("Provinsi ditemukan: %s", provinsi.Name)
// 8. Buat respons dengan data lengkap
hierarchy := map[string]interface{}{
"kecamatan": map[string]interface{}{
"id": kecamatan.Identifier[0].Value,
"name": kecamatan.Name,
},
"kelurahan": map[string]interface{}{
"id": kelurahan.Identifier[0].Value,
"name": kelurahan.Name,
},
"kota": map[string]interface{}{
"id": kota.Identifier[0].Value,
"name": kota.Name,
},
"provinsi": map[string]interface{}{
"id": provinsi.Identifier[0].Value,
"name": provinsi.Name,
},
}
return hierarchy, nil
}
// Helper function untuk min
func min(a, b int) int {
if a < b {
return a
}
return b
}
func (s *DatabaseService) GetHierarchyFromProvinsi(provinsiId string) (map[string]interface{}, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// 1. Ambil data provinsi
var provinsi Mongomaster.State
provinsiFilter := bson.M{
"identifier.0.value": provinsiId,
}
err := s.DBMongo.Collection("state").FindOne(ctx, provinsiFilter).Decode(&provinsi)
if err != nil {
log.Println("Error saat mencari provinsi:", err)
return nil, err
}
log.Printf("Provinsi ditemukan: %s", provinsi.Name)
// DEBUGGING: Tampilkan struktur data kota
// Ambil semua kota tanpa filter untuk memeriksa struktur data
allCitiesCursor, err := s.DBMongo.Collection("city").Find(ctx, bson.M{})
if err != nil {
log.Println("Error saat mengambil semua kota:", err)
return nil, err
}
var allCities []Mongomaster.City
if err = allCitiesCursor.All(ctx, &allCities); err != nil {
log.Println("Error saat decode semua kota:", err)
return nil, err
}
log.Printf("Total kota di database: %d", len(allCities))
// Periksa dan tampilkan format referensi di 3 kota pertama
for i, city := range allCities {
if i < 3 {
log.Printf("Kota: %s, State Reference: %+v", city.Name, city.State.Reference)
}
}
// Cari kota berdasarkan provinsi setelah melihat format referensi yang benar
var kotaList []map[string]interface{}
// Coba berbagai kemungkinan filter
filters := []bson.M{
{"state.reference": "provinsi/" + provinsiId},
{"state.reference": provinsiId},
{"state.display": provinsi.Name},
}
var kota []Mongomaster.City
var foundFilter string
for _, filter := range filters {
log.Printf("Mencoba filter kota: %v", filter)
kotaCursor, _ := s.DBMongo.Collection("city").Find(ctx, filter)
var tempKota []Mongomaster.City
if kotaCursor.All(ctx, &tempKota) == nil && len(tempKota) > 0 {
kota = tempKota
foundFilter = fmt.Sprintf("%v", filter)
log.Printf("Filter yang berhasil: %s, menemukan %d kota", foundFilter, len(kota))
break
}
}
// Jika semua filter gagal, gunakan pendekatan alternatif: manual matching
if len(kota) == 0 {
log.Println("Semua filter gagal, mencoba pendekatan manual matching")
// Cari kota yang memiliki referensi ke provinsi ini dengan cara apa pun
for _, city := range allCities {
stateRef := city.State.Reference
stateDisplay := city.State.Display
// Cek apakah referensi atau display cocok dengan provinsi
if strings.Contains(stateRef, provinsiId) ||
strings.EqualFold(stateDisplay, provinsi.Name) {
kota = append(kota, city)
}
}
log.Printf("Pendekatan manual menemukan %d kota", len(kota))
}
// Transform data kota
kotaList = make([]map[string]interface{}, 0)
for _, k := range kota {
kotaId := k.Identifier[0].Value
log.Printf("Memproses kota: %s (ID: %s)", k.Name, kotaId)
kotaItem := map[string]interface{}{
"id": kotaId,
"name": k.Name,
"kecamatan": []map[string]interface{}{},
}
// DEBUGGING: Tampilkan struktur data kecamatan
allDistrictsCursor, _ := s.DBMongo.Collection("district").Find(ctx, bson.M{})
var allDistricts []Mongomaster.District
if allDistrictsCursor.All(ctx, &allDistricts) == nil {
log.Printf("Total kecamatan di database: %d", len(allDistricts))
// Periksa kecamatan yang memiliki referensi ke kota ini
var kecamatanForCity []Mongomaster.District
for _, district := range allDistricts {
cityRef := district.City.Reference
cityDisplay := district.City.Display
// Cek apakah referensi atau display cocok dengan kota
if strings.Contains(cityRef, kotaId) ||
strings.EqualFold(cityDisplay, k.Name) {
kecamatanForCity = append(kecamatanForCity, district)
}
}
log.Printf("Menemukan %d kecamatan untuk kota %s", len(kecamatanForCity), k.Name)
// Proses kecamatan yang ditemukan
kecamatanList := make([]map[string]interface{}, 0)
for _, kec := range kecamatanForCity {
kecamatanId := kec.Identifier[0].Value
log.Printf("Memproses kecamatan: %s (ID: %s)", kec.Name, kecamatanId)
kecamatanItem := map[string]interface{}{
"id": kecamatanId,
"name": kec.Name,
"kelurahan": []map[string]interface{}{},
}
// DEBUGGING: Tampilkan struktur data kelurahan
allVillagesCursor, _ := s.DBMongo.Collection("village").Find(ctx, bson.M{})
var allVillages []Mongomaster.Village
if allVillagesCursor.All(ctx, &allVillages) == nil {
log.Printf("Total kelurahan di database: %d", len(allVillages))
// Periksa kelurahan yang memiliki referensi ke kecamatan ini
var kelurahanForDistrict []Mongomaster.Village
for _, village := range allVillages {
districtRef := village.District.Reference
districtDisplay := village.District.Display
// Cek apakah referensi atau display cocok dengan kecamatan
if strings.Contains(districtRef, kecamatanId) ||
strings.EqualFold(districtDisplay, kec.Name) {
kelurahanForDistrict = append(kelurahanForDistrict, village)
}
}
log.Printf("Menemukan %d kelurahan untuk kecamatan %s", len(kelurahanForDistrict), kec.Name)
// Proses kelurahan yang ditemukan
kelurahanList := make([]map[string]interface{}, 0)
for _, kel := range kelurahanForDistrict {
kelurahanItem := map[string]interface{}{
"id": kel.Identifier[0].Value,
"name": kel.Name,
}
kelurahanList = append(kelurahanList, kelurahanItem)
}
// Tambahkan kelurahan ke kecamatan
kecamatanItem["kelurahan"] = kelurahanList
}
kecamatanList = append(kecamatanList, kecamatanItem)
}
// Tambahkan kecamatan ke kota
kotaItem["kecamatan"] = kecamatanList
}
kotaList = append(kotaList, kotaItem)
}
// Buat response hierarki
hierarchy := map[string]interface{}{
"provinsi": map[string]interface{}{
"id": provinsi.Identifier[0].Value,
"name": provinsi.Name,
"kota": kotaList,
},
}
return hierarchy, nil
}