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("import data pasien") 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{} for idx, row := range rows { 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", }) continue } 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", }) continue } kelamin, err := strconv.Atoi(row[6]) if err != nil { log.Printf("row 6: %s, err: %v", row[6], err) continue } value := repository.ImportDataPasienParams{ NoRekamMedis: row[0], NamaPasien: row[1], Nik: pgtype.Text{String: row[2], Valid: len(row[2]) > 0}, NoBPJS: pgtype.Text{String: row[3], Valid: len(row[3]) > 0}, TpLahir: pgtype.Text{String: row[4], Valid: len(row[4]) > 0}, TglLahir: tanggalLahir, Kelamin: int8(kelamin), Kebangsaan: util.StringToIntPtr[int8](row[6]), Agama: util.StringToIntPtr[int8](row[7]), Suku: util.StringToIntPtr[int32](row[8]), Pendidikan: util.StringToIntPtr[int8](row[9]), Pekerjaan: util.StringToIntPtr[int8](row[10]), Hp: pgtype.Text{String: row[11], Valid: len(row[11]) > 0}, Email: pgtype.Text{String: row[12], Valid: len(row[12]) > 0}, StatusNikah: util.StringToIntPtr[int8](row[13]), Provinsi: util.StringToStringPtr(row[14]), Kabupaten: util.StringToIntPtr[int32](row[15]), Kecamatan: util.StringToIntPtr[int32](row[16]), Kelurahan: util.StringToIntPtr[int32](row[17]), Kodepos: util.StringToIntPtr[int32](row[18]), NamaJalan: pgtype.Text{String: row[19], Valid: len(row[19]) > 0}, HpPenjamin: pgtype.Text{String: row[20], Valid: len(row[20]) > 0}, NamaPenjamin: pgtype.Text{String: row[21], Valid: len(row[21]) > 0}, KtpPenjamin: pgtype.Text{String: row[22], Valid: len(row[22]) > 0}, HubunganPenjamin: util.StringToIntPtr[int8](row[23]), PendidikanPenjamin: util.StringToIntPtr[int8](row[24]), AlamatPenjamin: pgtype.Text{String: row[25], Valid: len(row[25]) > 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), }) continue } } 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), }) continue } 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.Nik.Valid { patient, err := repository.Store.FindPatientByNik(s.Store, r.Context(), value.Nik.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.Nik.String == patient.Nik.String { if patient.TanggalLahir.Before(value.TglLahir) { value.Nik.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), }) continue } 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), }) } continue } 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), }) continue } } } 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) }