go_import_excel_pg/internal/rest/handler.go
2024-03-06 09:15:08 +07:00

346 lines
10 KiB
Go

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)
}