package rest import ( "encoding/json" "fmt" "log" "net/http" "os" "strconv" "strings" "time" "git.nochill.in/nochill/excel_import_playground/internal" "git.nochill.in/nochill/excel_import_playground/internal/repository" "git.nochill.in/nochill/excel_import_playground/util" "github.com/gorilla/mux" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "github.com/xuri/excelize/v2" ) func (s *Server) ImportPatientHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") currentUser := internal.GetPayloadFromContext(r.Context()) file, header, err := r.FormFile("file") if err != nil { http.Error(w, "Invalid file", http.StatusBadRequest) return } if !strings.HasSuffix(header.Filename, ".xlsx") && !strings.HasSuffix(header.Filename, ".xls") { http.Error(w, "File is not an .xlsx or xls file", http.StatusBadRequest) return } if header.Size > 30<<20 { http.Error(w, "The uploaded file is too large.", http.StatusBadRequest) return } buffer := make([]byte, 512) // Create a buffer to store the file header if _, err = file.Read(buffer); err != nil { http.Error(w, "Could not read file", http.StatusInternalServerError) return } // contentType := http.DetectContentType(buffer) // Reset the read pointer of the file if _, err = file.Seek(0, 0); err != nil { http.Error(w, "Could not read file", http.StatusInternalServerError) return } f, err := excelize.OpenReader(file) if err != nil { http.Error(w, "Error opening Excel file", http.StatusInternalServerError) return } defer f.Close() rows, err := f.GetRows("PRODUCTION Pasien Setio") if err != nil { json.NewEncoder(w).Encode(err) return } // _, err = repository.Store.FindLastPatientInCertainFasyankes(s.Store, r.Context(), 2) if err != nil { w.WriteHeader(500) log.Println(err) json.NewEncoder(w).Encode(err) return } // tempArr := make([]repository.ImportDataPasienParams, len(rows)-1) var errorMsg []interface{} // var wg = &sync.WaitGroup{} for idx, row := range rows { // wg.Add(1) // go func(idx int, row []string) { if idx >= 1 { if row[0] == "" || row[1] == "" { errorMsg = append(errorMsg, map[string]any{ "baris": idx + 1, "status": "CRITICAL", "error_message": "kolom A 'no_rekam medis' dan kolom B 'nama_pasien' wajib diisi", }) return } tanggalLahir, err := time.Parse(util.TIME_PARSE_LAYOUT, row[5]) if err != nil { errorMsg = append(errorMsg, map[string]any{ "baris": idx + 1, "status": "CRITICAL", "error_message": "tanggal lahir wajib diisi", }) return } kelamin, err := strconv.Atoi(row[6]) if err != nil { log.Printf("row 6: %s, err: %v", row[6], err) return } value := repository.ImportDataPasienParams{ NoRekamMedis: row[0], NamaPasien: row[1], NoKTP: pgtype.Text{String: row[2], Valid: len(row[2]) > 0}, NoBPJS: pgtype.Text{String: row[3], Valid: len(row[3]) > 0}, TempatLahir: pgtype.Int4{Int32: 0, Valid: false}, TglLahir: tanggalLahir, Kelamin: int8(kelamin), Kebangsaan: pgtype.Int4{Int32: util.StringToInt[int32](row[7]), Valid: util.StringToInt[int32](row[7]) > 0}, Agama: pgtype.Int4{Int32: util.StringToInt[int32](row[8]), Valid: util.StringToInt[int32](row[8]) > 0}, Suku: pgtype.Int4{Int32: util.StringToInt[int32](row[9]), Valid: util.StringToInt[int32](row[9]) > 0}, Pendidikan: pgtype.Int4{Int32: util.StringToInt[int32](row[10]), Valid: util.StringToInt[int32](row[10]) > 0}, Pekerjaan: pgtype.Int4{Int32: util.StringToInt[int32](row[11]), Valid: util.StringToInt[int32](row[11]) > 0}, Hp: pgtype.Text{String: row[12], Valid: len(row[12]) > 0}, Email: pgtype.Text{String: row[13], Valid: len(row[13]) > 0}, StatusKawin: pgtype.Int4{Int32: util.StringToInt[int32](row[14]), Valid: util.StringToInt[int32](row[14]) > 0}, Provinsi: pgtype.Text{String: row[15], Valid: len(row[15]) > 0}, NamaJalan: pgtype.Text{String: row[16], Valid: len(row[16]) > 0}, NamaPenjamin: pgtype.Text{String: row[17], Valid: len(row[17]) > 0}, NikPenjamin: pgtype.Text{String: row[18], Valid: len(row[18]) > 0}, HubunganPenjamin: pgtype.Int2{Int16: util.StringToInt[int16](row[8]), Valid: util.StringToInt[int16](row[8]) > 0}, HpPenjamin: pgtype.Text{String: row[20], Valid: len(row[20]) > 0}, } patientExist, err := repository.Store.FindPatientByNoRm(s.Store, r.Context(), value.NoRekamMedis) if err != nil { if err != pgx.ErrNoRows { errorMsg = append(errorMsg, map[string]any{ "no_rm": value.NoRekamMedis, "status": "CRITICAL", "message": fmt.Sprintf("Terjadi kesalahan sistem, mencari data pasien %v", err), }) return } } if patientExist.NoRm != "" { if value.NoRekamMedis == patientExist.NoRm { updatedNoRekamMedis, err := repository.Store.GenerateNoRm(s.Store, r.Context(), int32(currentUser.FasyankesId)) if err != nil { errorMsg = append(errorMsg, map[string]any{ "no_rm": value.NoRekamMedis, "status": "CRITICAL", "message": fmt.Sprintf("Terjadi kesalahan sistem, gagal generate NoRM %v", err), }) return } errorMsg = append(errorMsg, map[string]any{ "no_rm": value.NoRekamMedis, "status": "WARNING", "message": fmt.Sprintf("No rekam medis %s sudah ada, maka no rekam medis diganti dengan %s", value.NoRekamMedis, updatedNoRekamMedis), }) value.NoRekamMedis = updatedNoRekamMedis } } if value.NoKTP.Valid { patient, err := repository.Store.FindPatientByNik(s.Store, r.Context(), value.NoKTP.String) if err != nil { if err != pgx.ErrNoRows { errorMsg = append(errorMsg, map[string]any{ "no_rm": value.NoRekamMedis, "status": "CRITICAL", "message": fmt.Sprintf("Terjadi kesalahan sistem, gagal mendapatakan data pasien %v", err), }) } } if value.NoKTP.String == patient.Nik.String { if patient.TanggalLahir.Before(value.TglLahir) { value.NoKTP.Valid = false } else { _, err := repository.Store.UpdatePatient(s.Store, r.Context(), repository.UpdatePatientParams{ Nik: repository.UpdateableField[pgtype.Text]{IsFilled: true, Value: pgtype.Text{Valid: false, String: ""}}, }, int32(patient.ID)) if err != nil { errorMsg = append(errorMsg, map[string]any{ "no_rm": value.NoRekamMedis, "status": "CRITICAL", "message": fmt.Sprintf("Terjadi kesalahan sistem, gagal mendapatakan update pasien lama karena NIK sama %v", err), }) return } errorMsg = append(errorMsg, map[string]any{ "no_rm": value.NoRekamMedis, "status": "WARNING", "message": fmt.Sprintf("NIK kembar dengan pasien yang ada di sistem noRm: %s %s, mohon dicek kembali current user: %v"), }) } } } if value.NoBPJS.Valid { patient, err := repository.Store.FindPatientByBPJSCode(s.Store, r.Context(), value.NoBPJS.String) if err != nil { if err != pgx.ErrNoRows { errorMsg = append(errorMsg, map[string]any{ "no_rm": value.NoRekamMedis, "status": "CRITICAL", "message": fmt.Sprintf("Terjadi kesalahan sistem, gagal mendapatakan data pasien dengan BPJS %v", err), }) } } if patient.ID != 0 { if patient.TanggalLahir.Before(value.TglLahir) { value.NoBPJS = pgtype.Text{Valid: false, String: ""} } else { _, err := repository.Store.UpdatePatient( s.Store, r.Context(), repository.UpdatePatientParams{ NoKartuPesertaBPJS: repository.UpdateableField[pgtype.Text]{IsFilled: true, Value: pgtype.Text{Valid: false, String: ""}}, }, int32(patient.ID), ) if err != nil { errorMsg = append(errorMsg, map[string]any{ "no_rm": value.NoRekamMedis, "status": "CRITICAL", "message": fmt.Sprintf("Terjadi kesalahan sistem, gagal mendapatakan update pasien dengan BPJS %v", err), }) } return } errorMsg = append(errorMsg, map[string]any{ "no_rm": value.NoRekamMedis, "status": "WARNING", "message": fmt.Sprintf("No KartuBPJS ada yang sama dengan pasien dengan no rm yang ada di sistem: noRm: %s noBpjs: %s, mohon dicek kembali, NO BPJS pasien import: %s", patient.NoRm, patient.NoKartuPesertaBPJS.String, value.NoBPJS.String, ), }) } } err = repository.Store.ImportPatientTx(s.Store, r.Context(), value, int32(currentUser.UserId), int32(currentUser.FasyankesId)) if err != nil { errorMsg = append(errorMsg, map[string]any{ "no_rm": value.NoRekamMedis, "status": "CRITICAL", "message": fmt.Sprintf("Terjadi kesalahan sistem, gagal saat import pasien dengan %v", err), }) return } } // wg.Done() // }(idx, row) } // wg.Wait() if len(errorMsg) > 0 { jsonMarshal, _ := json.MarshalIndent(errorMsg, "", " ") if err := os.WriteFile("foo.txt", []byte(jsonMarshal), 0666); err != nil { log.Fatal(err) } } a := map[string]any{ "halo": "halo", "file": "foo.txt", // "contentType": contentType, // "patient": tempArr, // "errorData": errorMsg, } w.WriteHeader(200) json.NewEncoder(w).Encode(a) } func validateFile(r *http.Request) error { return nil } type updatePatientParams struct { NamaPasien string `json:"patient_name"` } func (s *Server) UpdatePatient(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) var req updatePatientParams idParams, ok := vars["id"] if !ok { fmt.Println("id is missing in parameters") } id, err := strconv.Atoi(idParams) if err != nil { w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(err) return } err = json.NewDecoder(r.Body).Decode(&req) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } updatedUser, err := repository.Store.UpdatePatient(s.Store, r.Context(), repository.UpdatePatientParams{ NamaPasien: repository.UpdateableField[string]{IsFilled: true, Value: req.NamaPasien}, }, int32(id)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(updatedUser) }