534 lines
12 KiB
Go
534 lines
12 KiB
Go
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
|
|
}
|