package practitioner import ( "api-poliklinik/internal/database" "api-poliklinik/pkg/database/mongo" connDatabase "api-poliklinik/pkg/database/satu_data" "api-poliklinik/pkg/models/mongo/practitioner" _struct "api-poliklinik/pkg/models/struct" "github.com/gin-gonic/gin" "go.mongodb.org/mongo-driver/bson/primitive" "log" "net/http" "os" "strings" "time" ) func Migratepractitioner(c *gin.Context) { db := database.New().GetDB("simrs") simrs := connDatabase.NewDatabaseService(db) dataPractitioner := simrs.Getdokter() if dataPractitioner == nil || len(dataPractitioner) == 0 { c.JSON(http.StatusNotFound, gin.H{ "status": "error", "message": "Tidak ada data pasien untuk dimigrasi", }) return } local := os.Getenv("MONGODB_DEV_LOCAL") mongoDBConn := database.New(local).GetMongoDB() if mongoDBConn == nil { c.JSON(http.StatusInternalServerError, gin.H{ "status": "error", "message": "Koneksi database MongoDB gagal", }) return } mongoDB := mongo.NewDatabaseServiceMongo(mongoDBConn) migratedCount := 0 failedCount := 0 var migratedIDs []string for _, dokter := range dataPractitioner { objectID := primitive.NewObjectID() fullName := dokter.NamaDokter humanName := ParseDoctorName(fullName) var fhirDokter = practitioner.Practitioner{ ResourceType: "Practitioner", ID: objectID, Active: true, } fhirDokter.Identifier = []_struct.Identifier{ { Use: "usual", Type: _struct.CodeableConcept{ Coding: []_struct.Coding{ { System: "", Version: "", Code: "IDSIM", Display: "SIMRS ID", UserSelected: true, }, }, Text: "SIMRS ID", }, System: "", Value: dokter.IDDokter, Period: _struct.Period{ Start: "", End: "", }, Assigner: _struct.Reference{ Reference: "", Display: "", }, }, { Use: "usual", Type: _struct.CodeableConcept{ Coding: []_struct.Coding{ { System: "", Version: "", Code: "KDDPJP", Display: "Kode Dokter Penanggung Jawab", UserSelected: true, }, }, Text: "Kode Dokter Penanggung Jawab", }, System: "", Value: dokter.KodeDpjp, Period: _struct.Period{ Start: "", End: "", }, Assigner: _struct.Reference{ Reference: "", Display: "", }, }, { Use: "usual", Type: _struct.CodeableConcept{ Coding: []_struct.Coding{ { System: "", Version: "", Code: "NIP", Display: "Nomor Induk Pegawai", UserSelected: true, }, }, Text: "Nomor Induk Pegawai", }, System: "", Value: dokter.NIP, Period: _struct.Period{ Start: "", End: "", }, Assigner: _struct.Reference{ Reference: "", Display: "", }, }, { Use: "usual", Type: _struct.CodeableConcept{ Coding: []_struct.Coding{ { System: "", Version: "", Code: "HFIS", Display: "HFIS Code", UserSelected: true, }, }, Text: "HFIS", }, System: "", Value: "", Period: _struct.Period{ Start: "", End: "", }, Assigner: _struct.Reference{ Reference: "", Display: "", }, }, { Use: "usual", Type: _struct.CodeableConcept{ Coding: []_struct.Coding{ { System: "", Version: "", Code: "SATUSEHAT", Display: "SatuSehat Code", UserSelected: true, }, }, Text: "SATUSEHAT", }, System: "", Value: "", Period: _struct.Period{ Start: "", End: "", }, Assigner: _struct.Reference{ Reference: "", Display: "", }, }, } fhirDokter.Name = []_struct.HumanName{humanName} fhirDokter.Telecom = []_struct.ContactPoint{ { System: "phone", Value: dokter.NomorHP, Use: "mobile", Rank: "1", Period: _struct.Period{ Start: "", End: "", }, }, { System: "email", Value: dokter.Email, Use: "work", Rank: "1", Period: _struct.Period{ Start: "", End: "", }, }, } fhirDokter.Gender = "" fhirDokter.BirthDate = "" fhirDokter.Address = []_struct.Address{ { Use: "home", Type: "both", Text: "", Line: []string{""}, Village: "", District: "", City: "", State: "", PostalCode: "", Country: "", Period: _struct.Period{ Start: "", End: "", }, Extension: []_struct.Extension{ { URL: "", Extension: []_struct.ExtensionDetail{ { URL: "state", ValueDisplay: "", ValueCode: "", }, { URL: "city", ValueDisplay: "", ValueCode: "", }, { URL: "district", ValueDisplay: "", ValueCode: "", }, { URL: "village", ValueDisplay: "", ValueCode: "", }, { URL: "rt", ValueDisplay: "", ValueCode: "", }, { URL: "rw", ValueDisplay: "", ValueCode: "", }, }, }, }, }, } fhirDokter.Qualification = []_struct.Qualification{ { Identifier: []_struct.Identifier{ { Use: "usual", Type: _struct.CodeableConcept{ Coding: []_struct.Coding{ { System: "", Version: "", Code: "SIP", Display: "Surat Ijin Praktek", UserSelected: true, }, }, Text: "SIP", }, System: "", Value: "", Period: _struct.Period{ Start: "", End: dokter.QuSIP, }, Assigner: _struct.Reference{ Reference: "", Display: "", }, }, { Use: "usual", Type: _struct.CodeableConcept{ Coding: []_struct.Coding{ { System: "", Version: "", Code: "SPK", Display: "Surat Perintah Kerja", UserSelected: true, }, }, Text: "SPK", }, System: "", Value: "", Period: _struct.Period{ Start: "", End: dokter.QuSPK, }, Assigner: _struct.Reference{ Reference: "", Display: "", }, }, }, Code: _struct.CodeableConcept{ Coding: []_struct.Coding{ { System: "http://terminology.hl7.org/CodeSystem/v2-0360/2.7", Version: "", Code: "MD", Display: "Doctor of Medicine", UserSelected: true, }, }, Text: "", }, Period: _struct.Period{ Start: "", End: "", }, Issuer: _struct.Reference{ Reference: "", Display: "", }, }, } // Communication fhirDokter.Communication = []_struct.Communication{ { Language: _struct.CodeableConcept{ Coding: []_struct.Coding{ { System: "", Version: "", Code: "id", Display: "Indonesian", UserSelected: true, }, }, Text: "Bahasa Indonesia", }, }, { Language: _struct.CodeableConcept{ Coding: []_struct.Coding{ { System: "", Version: "", Code: "en", Display: "English", UserSelected: true, }, }, Text: "Bahasa Inggris", }, }, } // Extension fhirDokter.Extension = []_struct.Extension{ { URL: "", Extension: []_struct.ExtensionDetail{ { URL: "birthPlace", ValueDisplay: "", ValueCode: "", }, { URL: "national", ValueDisplay: "Warga Negara Indonesia", ValueCode: "WNI", }, { URL: "religion", ValueDisplay: "", ValueCode: "", }, { URL: "smf", ValueDisplay: "SMF", ValueCode: dokter.SMF, }, { URL: "category", ValueDisplay: dokter.Kategori, ValueCode: dokter.Kategori, }, }, }, } err := mongoDB.InsertPractitioner(fhirDokter) if err != nil { log.Printf("Gagal migrasi data praktisi %s: %v", dokter.IDDokter, err) failedCount++ continue } migratedIDs = append(migratedIDs, objectID.Hex()) migratedCount++ } c.JSON(http.StatusOK, gin.H{ "status": "success", "message": "Migrasi data praktisi ke FHIR berhasil", "total": len(dataPractitioner), "migrated": migratedCount, "failed": failedCount, "migrated_ids": migratedIDs, "timestamp": time.Now().Format(time.RFC3339), }) } // ParseDoctorName memisahkan nama dokter menjadi komponen-komponennya func ParseDoctorName(fullName string) _struct.HumanName { // Inisialisasi variabel hasil var humanName _struct.HumanName humanName.Use = "official" humanName.Text = fullName // Simpan teks lengkap // Hilangkan spasi berlebih fullName = strings.TrimSpace(fullName) // Cari gelar depan (prefix) prefixPatterns := []string{"dr.", "DR.", "Dr.", "drg.", "DRG.", "Drg.", "prof.", "PROF.", "Prof."} var prefix string var nameWithoutPrefix string for _, pattern := range prefixPatterns { if strings.HasPrefix(strings.ToLower(fullName), strings.ToLower(pattern)) { prefix = pattern nameWithoutPrefix = strings.TrimSpace(fullName[len(pattern):]) break } } if prefix != "" { humanName.Prefix = []string{strings.TrimSpace(prefix)} } else { humanName.Prefix = []string{} nameWithoutPrefix = fullName } // Cari gelar belakang (suffix) - seperti Sp.XX, M.Kes, dll var suffixList []string var nameWithoutSuffix string // Pola-pola gelar belakang yang umum suffixPatterns := []string{ "Sp.PD", "Sp.B", "Sp.OG", "Sp.A", "Sp.S", "Sp.THT", "Sp.KK", "Sp.JP", "Sp.M", "Sp.OT", "M.Kes", "M.Si", "M.Biomed", "S.Kep", "S.Gz", "S.Farm", "S.Kep, Ns", "Ph.D", "S.Psi", "MARS", "MPH", "MMR", "MH", "Ners", "MMRS", } // Pisahkan string berdasarkan koma parts := strings.Split(nameWithoutPrefix, ",") if len(parts) > 1 { // Jika ada koma, bagian setelah koma adalah gelar belakang nameWithoutSuffix = strings.TrimSpace(parts[0]) // Proses bagian setelah koma untuk mendapatkan gelar-gelar suffixPart := strings.TrimSpace(parts[1]) // Pisahkan gelar jika ada beberapa (dipisahkan spasi) suffixCandidates := strings.Split(suffixPart, " ") for _, candidate := range suffixCandidates { if candidate != "" { suffixList = append(suffixList, strings.TrimSpace(candidate)) } } } else { // Jika tidak ada koma, periksa apakah ada gelar belakang yang umum nameWithoutSuffix = nameWithoutPrefix for _, pattern := range suffixPatterns { if strings.Contains(nameWithoutPrefix, pattern) { // Temukan posisi pattern index := strings.Index(strings.ToUpper(nameWithoutPrefix), strings.ToUpper(pattern)) if index > 0 { nameWithoutSuffix = strings.TrimSpace(nameWithoutPrefix[:index]) suffixList = append(suffixList, pattern) break } } } } humanName.Suffix = suffixList // Pisahkan nama menjadi nama keluarga (family) dan nama depan (given) nameParts := strings.Split(nameWithoutSuffix, " ") if len(nameParts) > 1 { // Nama keluarga biasanya ada di akhir humanName.Family = nameParts[len(nameParts)-1] // Nama depan adalah semua kata sebelum nama keluarga humanName.Given = nameParts[:len(nameParts)-1] } else if len(nameParts) == 1 { // Jika hanya ada satu kata, itu dianggap sebagai nama keluarga humanName.Family = nameParts[0] humanName.Given = []string{} } else { // Jika tidak ada nama, set nilai default humanName.Family = "" humanName.Given = []string{} } // Set period kosong humanName.Period = _struct.Period{ Start: "", End: "", } return humanName }