572 lines
16 KiB
Go
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
|
|
}
|