Compare commits

...
4 Commits
9 changed files with 230 additions and 50 deletions

No files matched your search

+7 -5
View File
@@ -50,11 +50,13 @@ type TeleponPasienModel struct {
}
type DokterOperasiModel struct {
ID string `db:"id"`
Nip sql.NullString `db:"nip"`
NamaDepan sql.NullString `db:"nama_depan"`
NamaBelakang sql.NullString `db:"nama_belakang"`
SatuanKerja string `db:"satker"`
ID string `db:"id"`
Nip sql.NullString `db:"nip"`
NamaDepan sql.NullString `db:"nama_depan"`
NamaBelakang sql.NullString `db:"nama_belakang"`
SatuanKerja string `db:"satker"`
GelarDepan []string
GelarBelakang []string
}
type DetailPasienOperasi struct {
+82 -33
View File
@@ -2,6 +2,7 @@ package antrianoperasi
import (
"antrian-operasi/internal/database"
"antrian-operasi/internal/domain/reference/dokter"
"antrian-operasi/internal/shared"
queryUtils "antrian-operasi/internal/utils/query"
"database/sql"
@@ -48,7 +49,7 @@ func NewRepository(dbService database.Service) IAntrianOperasiRepository {
"\"Kode_diagnosa\"", "\"Diagnosa\"", "\"Jenis_diagnosa\"", "\"FK_pasien_operasi_diagnosa_pasien_operasi_ID\"", "FK_pasien_operasi_diagnosa_pasien_operasi_ID",
"\"Kode_tindakan\"", "\"Tindakan\"", "\"Tindakan_tambahan\"", "\"FK_pasien_operasi_tindakan_pasien_operasi_ID\"", "FK_pasien_operasi_tindakan_pasien_operasi_ID",
"\"data_pasien_operasi_id\"", "\"data_pegawai_id\"", "data_pasien_operasi_id",
"no_urut_spesialis", "no_urut_sub_spesialis", "no_ktp", "no_rekam_medis", "nama_pasien", "status_operasi",
"no_urut_spesialis", "no_urut_sub_spesialis", "no_ktp", "no_rekam_medis", "nama_pasien", "status_operasi", "id_kategori", "id_spesialis", "id_subspesialis",
}).
SetAllowedTables([]string{TBL_NAME, TBL_DIAGNOSA_OPERASI})
queryBuilder.SetSecurityOptions(false, 100)
@@ -402,22 +403,25 @@ func (r antrianOperasiRepo) SearchableListAntrianOperasi(c context.Context, q An
},
}
var resultDiagnosa []DiagnosaOperasiModel
err = r.queryBuilder.ExecuteQuery(c, dbconn, queryDiagnosa, &resultDiagnosa)
if err != nil {
log.Printf("Unable to execute query diagnosa : %s", err)
return result, err
}
// if query id specified, no need to attach support data
if q.Id == "" {
var resultDiagnosa []DiagnosaOperasiModel
err = r.queryBuilder.ExecuteQuery(c, dbconn, queryDiagnosa, &resultDiagnosa)
if err != nil {
log.Printf("Unable to execute query diagnosa : %s", err)
return result, err
}
// attach support data to parent
shared.MapChildToParent(
result.Data, resultDiagnosa,
func(o *PasienOperasi) string { return o.ID },
func(d DiagnosaOperasiModel) string { return d.AntrianId },
func(o *PasienOperasi, d DiagnosaOperasiModel) {
o.Diagnosa = append(o.Diagnosa, d.Diagnosa.String)
},
)
// attach support data to parent
shared.MapChildToParent(
result.Data, resultDiagnosa,
func(o *PasienOperasi) string { return o.ID },
func(d DiagnosaOperasiModel) string { return d.AntrianId },
func(o *PasienOperasi, d DiagnosaOperasiModel) {
o.Diagnosa = append(o.Diagnosa, d.Diagnosa.String)
},
)
}
return result, nil
}
@@ -580,6 +584,7 @@ func (r antrianOperasiRepo) GetAntrianOperasiById(c context.Context, id string)
}
// query dokter
var resultDokterModel []dokter.DokterModel
queryDokter := queryUtils.DynamicQuery{
From: TBL_DOKTER_OPERASI,
Aliases: "dpodp",
@@ -588,7 +593,7 @@ func (r antrianOperasiRepo) GetAntrianOperasiById(c context.Context, id string)
{Expression: "dp.NIP", Alias: "nip"},
{Expression: "dp.Nama_depan", Alias: "nama_depan"},
{Expression: "dp.Nama_belakang", Alias: "nama_belakang"},
{Expression: "dk.Nama_ksm", Alias: "satker"},
{Expression: "dk.Nama_ksm", Alias: "nama_ksm"},
},
Filters: []queryUtils.FilterGroup{
{
@@ -625,12 +630,27 @@ func (r antrianOperasiRepo) GetAntrianOperasiById(c context.Context, id string)
},
}
err = r.queryBuilder.ExecuteQuery(c, dbconn, queryDokter, &result.ResultDokterOperasi)
err = r.queryBuilder.ExecuteQuery(c, dbconn, queryDokter, &resultDokterModel)
if err != nil {
log.Printf("Unable to execute dokter query : %s", err)
return result, err
}
//fetch gelar
resultDokterModel = dokter.FetchGelar(c, r.queryBuilder, dbconn, resultDokterModel)
//map to result.ResultDokterOperasi
for _, dokter := range resultDokterModel {
result.ResultDokterOperasi = append(result.ResultDokterOperasi, DokterOperasiModel{
ID: dokter.ID,
Nip: shared.NullString(dokter.Nip),
NamaBelakang: shared.NullString(dokter.NamaBelakang.String),
NamaDepan: shared.NullString(dokter.NamaDepan.String),
GelarDepan: dokter.GelarDepan,
GelarBelakang: dokter.GelarBelakang,
})
}
return result, nil
}
@@ -706,6 +726,14 @@ func (r antrianOperasiRepo) UpdateAntrianOperasi(c context.Context, id string, r
}
func (r antrianOperasiRepo) UpdateStatusAntrianOperasi(c context.Context, id string, req StatusPasienRequest) (StatusPasienRequest, error) {
// get nomor antrian by antrian id
q := AntrianQuery{Id: id}
resultAntrian, err := r.SearchableListAntrianOperasi(c, q)
if err != nil {
return req, err
}
selectedAntrian := resultAntrian.Data[0]
// Update main table
updateMainQuery := queryUtils.UpdateData{
Columns: []string{
@@ -717,8 +745,11 @@ func (r antrianOperasiRepo) UpdateStatusAntrianOperasi(c context.Context, id str
}
if req.StatusOperasi == "2" {
updateMainQuery.Columns = append(updateMainQuery.Columns, "\"Tanggal_selesai_operasi\"")
updateMainQuery.Values = append(updateMainQuery.Values, req.TglSelesai)
addedColumns := []string{"\"Tanggal_selesai_operasi\"", "\"Nomor\"", "\"Nomor_spesialis\"", "\"Nomor_sub_spesialis\""}
addedValues := []interface{}{req.TglSelesai, selectedAntrian.NoUrutKategori, selectedAntrian.NoUrutSpesialis, selectedAntrian.NoUrutSubSpesialis}
updateMainQuery.Columns = append(updateMainQuery.Columns, addedColumns...)
updateMainQuery.Values = append(updateMainQuery.Values, addedValues...)
}
filters := []queryUtils.FilterGroup{
@@ -970,6 +1001,9 @@ func (r antrianOperasiRepo) fixingListAntrian(c context.Context, dbconn *sqlx.DB
Query: queryUtils.DynamicQuery{
Fields: []queryUtils.SelectField{
{Expression: "dpo.id", Alias: "id"},
{Expression: "dko.id", Alias: "id_kategori"},
{Expression: "ds.id", Alias: "id_spesialis"},
{Expression: "dss.id", Alias: "id_subspesialis"},
{Expression: "dpo.Tanggal_daftar", Alias: "tanggal_daftar"},
{Expression: "dpo.No_KTP", Alias: "no_ktp"},
{Expression: "dpo.No_rekam_medis", Alias: "no_rekam_medis"},
@@ -1064,22 +1098,26 @@ func (r antrianOperasiRepo) fixingListAntrian(c context.Context, dbconn *sqlx.DB
}
typeIdColumn := ""
typeIdColumnAlias := ""
// selecting windows functions by type
switch q.Type {
case "kategori":
typeIdColumn = "dko.id"
typeIdColumn = "dpo.Kategori_operasi"
typeIdColumnAlias = "id_kategori"
query.CTEs[0].Query.WindowFunctions = append(query.CTEs[0].Query.WindowFunctions, wfKategori, wfSpesialis, wfSubSpesialis)
query.Fields = append(query.Fields, queryUtils.SelectField{Expression: "no_urut_kategori"})
query.Sort = append(query.Sort, queryUtils.SortField{Column: "no_urut_kategori", Order: "ASC"})
case "spesialis":
typeIdColumn = "ds.id"
typeIdColumn = "dpo.Spesialis"
typeIdColumnAlias = "id_spesialis"
query.CTEs[0].Query.WindowFunctions = append(query.CTEs[0].Query.WindowFunctions, wfSpesialis, wfSubSpesialis)
query.Fields = append(query.Fields, queryUtils.SelectField{Expression: "no_urut_spesialis"})
query.Sort = append(query.Sort, queryUtils.SortField{Column: "no_urut_spesialis", Order: "ASC"})
case "sub-spesialis":
typeIdColumn = "dss.id"
typeIdColumn = "dpo.Sub_spesialis"
typeIdColumnAlias = "id_subspesialis"
query.CTEs[0].Query.WindowFunctions = append(query.CTEs[0].Query.WindowFunctions, wfSubSpesialis)
query.Fields = append(query.Fields, queryUtils.SelectField{Expression: "no_urut_sub_spesialis"})
query.Sort = append(query.Sort, queryUtils.SortField{Column: "no_urut_sub_spesialis", Order: "ASC"})
@@ -1100,7 +1138,7 @@ func (r antrianOperasiRepo) fixingListAntrian(c context.Context, dbconn *sqlx.DB
var selectFilterCount []queryUtils.DynamicFilter
if q.TypeID != 0 && q.Type != "all" {
selectFilter = append(selectFilter, queryUtils.DynamicFilter{Column: typeIdColumn, Operator: queryUtils.OpEqual, Value: q.TypeID})
selectFilter = append(selectFilter, queryUtils.DynamicFilter{Column: typeIdColumnAlias, Operator: queryUtils.OpEqual, Value: q.TypeID})
selectFilterCount = append(selectFilterCount, queryUtils.DynamicFilter{Column: typeIdColumn, Operator: queryUtils.OpEqual, Value: q.TypeID})
}
@@ -1129,25 +1167,36 @@ func (r antrianOperasiRepo) fixingListAntrian(c context.Context, dbconn *sqlx.DB
selectFilterCount = append(selectFilterCount, queryUtils.DynamicFilter{Column: "dpo.Status_operasi", Operator: queryUtils.OpEqual, Value: q.Status})
}
// search by id antrian. removing all filters
if q.Id != "" {
selectFilter = []queryUtils.DynamicFilter{} // reset select filter
selectFilterCount = []queryUtils.DynamicFilter{} // reset select filter count
selectFilter = append(selectFilter, queryUtils.DynamicFilter{Column: "id", Operator: queryUtils.OpEqual, Value: q.Id})
}
// wiring all select filter
query.Filters = append(query.Filters, queryUtils.FilterGroup{Filters: selectFilter, LogicOp: "AND"})
queryCount.Filters = append(queryCount.Filters, queryUtils.FilterGroup{Filters: selectFilterCount, LogicOp: "AND"})
countData, err := r.queryBuilder.ExecuteCount(c, dbconn, queryCount)
if err != nil {
log.Printf("Unable to execute query count : %s ", err)
return result, err
// skipping count data if query id specified
if q.Id == "" {
countData, err := r.queryBuilder.ExecuteCount(c, dbconn, queryCount)
if err != nil {
log.Printf("Unable to execute query count : %s ", err)
return result, err
}
result.Paging.Limit = q.Limit
result.Paging.Offset = q.Offset
result.Paging.Total = int(countData)
result.Paging.CalculatePagingInfo()
}
result.Paging.Limit = q.Limit
result.Paging.Offset = q.Offset
result.Paging.Total = int(countData)
result.Paging.CalculatePagingInfo()
// query data
queryData := query
queryData.Limit = q.Limit
queryData.Offset = q.Offset
err = r.queryBuilder.ExecuteQuery(
err := r.queryBuilder.ExecuteQuery(
c, dbconn, queryData, &result.Data)
if err != nil {
log.Printf("Unable to execute query data : %s", err)
@@ -62,6 +62,7 @@ type CreatePasienOperasiRequest struct {
}
type AntrianQuery struct {
Id string `form:"id"`
Search string `form:"search"`
Type string `form:"type,default=all" binding:"omitempty,oneof=all kategori spesialis sub-spesialis"`
TypeID int `form:"type_id,default=0"`
+7 -1
View File
@@ -80,7 +80,13 @@ func (model DetailPasienOperasiResultQuery) MapToResponse() DetailPasienOperasiR
}
for _, dk := range model.ResultDokterOperasi {
joinedName := strings.ToUpper(dk.NamaDepan.String) + " " + strings.ToUpper(dk.NamaBelakang.String)
namaDepan := strings.ToUpper(dk.NamaDepan.String)
namaBelakang := strings.ToUpper(dk.NamaBelakang.String)
gelarDepan := strings.Join(dk.GelarDepan, " ")
gelarBelakang := strings.Join(dk.GelarBelakang, ", ")
joinedName := gelarDepan + " " + namaDepan + " " + namaBelakang + " " + gelarBelakang
result.DokterPelaksanaItems = append(result.DokterPelaksanaItems, DokterPelaksanaItemRequest{
Id: dk.ID,
Nip: &dk.Nip.String,
@@ -38,9 +38,9 @@ func TestParsingDokter(t *testing.T) {
func TestParsingListDokter(t *testing.T) {
listModel := ListDokterModel{
DokterModel{"test-id-1", "test-nip-1", shared.NullString("A"), shared.NullString("B"), sql.NullString{}, "test-ksm-1"},
DokterModel{"test-id-2", "test-nip-2", shared.NullString("C"), shared.NullString("D"), sql.NullString{}, "test-ksm-2"},
DokterModel{"test-id-3", "test-nip-3", shared.NullString("E"), shared.NullString("F"), sql.NullString{}, "test-ksm-3"},
DokterModel{"test-id-1", "test-nip-1", shared.NullString("A"), shared.NullString("B"), sql.NullString{}, "test-ksm-1", []string{}, []string{}},
DokterModel{"test-id-2", "test-nip-2", shared.NullString("C"), shared.NullString("D"), sql.NullString{}, "test-ksm-2", []string{}, []string{}},
DokterModel{"test-id-3", "test-nip-3", shared.NullString("E"), shared.NullString("F"), sql.NullString{}, "test-ksm-3", []string{}, []string{}},
}
t.Run("test length model list and list response", func(t *testing.T) {
+13 -6
View File
@@ -6,12 +6,19 @@ import (
)
type DokterModel struct {
ID string `json:"id" db:"id"`
Nip string `json:"nip" db:"nip"`
NamaDepan sql.NullString `json:"nama_depan" db:"nama_depan"`
NamaBelakang sql.NullString `json:"nama_belakang" db:"nama_belakang"`
HfisCode sql.NullString `json:"hfis_code" db:"hfis_code"`
NamaKsm string `json:"nama_ksm" db:"nama_ksm"`
ID string `json:"id" db:"id"`
Nip string `json:"nip" db:"nip"`
NamaDepan sql.NullString `json:"nama_depan" db:"nama_depan"`
NamaBelakang sql.NullString `json:"nama_belakang" db:"nama_belakang"`
HfisCode sql.NullString `json:"hfis_code" db:"hfis_code"`
NamaKsm string `json:"nama_ksm" db:"nama_ksm"`
GelarDepan []string
GelarBelakang []string
}
type GelarModel struct {
Gelar string `db:"gelar"`
IDDokter string `db:"id_dokter"`
}
type DokterResponse struct {
@@ -9,10 +9,16 @@ import (
queryUtils "antrian-operasi/internal/utils/query"
"context"
"github.com/jmoiron/sqlx"
)
const DB_NAME = "db_antrian"
const TBL_NAME = "data_pegawai"
const TBL_GELAR_DEPAN = "daftar_gelar_depan"
const TBL_GELAR_BELAKANG = "daftar_gelar_belakang"
const TBL_RELASI_GELAR_DEPAN = "data_pegawai_daftar_gelar_depan"
const TBL_RELASI_GELAR_BLKG = "data_pegawai_daftar_gelar_belakang"
type IDokterRepository interface {
SearchableListDokter(c context.Context, search string, limit int, offset int) (ListDokterModelPaginate, error)
@@ -74,6 +80,108 @@ func baseSelectQuery() queryUtils.DynamicQuery {
return query
}
func FetchGelar(c context.Context, qb *queryUtils.QueryBuilder, dbconn *sqlx.DB, listDokter []DokterModel) []DokterModel {
var listGelarDepan []GelarModel
var listGelarBelakang []GelarModel
dokterIds := make([]string, 0, len(listDokter))
for _, dokter := range listDokter {
dokterIds = append(dokterIds, dokter.ID)
}
queryGelarDepan := queryUtils.DynamicQuery{
Fields: []queryUtils.SelectField{
{Expression: "rgd.data_pegawai_id", Alias: "id_dokter"},
{Expression: "gd.Gelar_depan", Alias: "gelar"},
},
From: TBL_RELASI_GELAR_DEPAN,
Aliases: "rgd",
Joins: []queryUtils.Join{
{
Type: "LEFT",
Table: TBL_GELAR_DEPAN,
Alias: "gd",
OnConditions: queryUtils.FilterGroup{
Filters: []queryUtils.DynamicFilter{
{
Column: "gd.id", Operator: queryUtils.OpEqual, Value: "rgd.daftar_gelar_depan_id",
},
},
},
},
},
Filters: []queryUtils.FilterGroup{
{
Filters: []queryUtils.DynamicFilter{
{
Column: "rgd.data_pegawai_id", Operator: queryUtils.OpIn, Value: dokterIds,
},
},
},
},
}
queryGelarBelakang := queryUtils.DynamicQuery{
Fields: []queryUtils.SelectField{
{Expression: "rgb.data_pegawai_id", Alias: "id_dokter"},
{Expression: "gb.Gelar_belakang", Alias: "gelar"},
},
From: TBL_RELASI_GELAR_BLKG,
Aliases: "rgb",
Joins: []queryUtils.Join{
{
Type: "LEFT",
Table: TBL_GELAR_BELAKANG,
Alias: "gb",
OnConditions: queryUtils.FilterGroup{
Filters: []queryUtils.DynamicFilter{
{
Column: "gb.id", Operator: queryUtils.OpEqual, Value: "rgb.daftar_gelar_belakang_id",
},
},
},
},
},
Filters: []queryUtils.FilterGroup{
{
Filters: []queryUtils.DynamicFilter{
{
Column: "rgb.data_pegawai_id", Operator: queryUtils.OpIn, Value: dokterIds,
},
},
},
},
}
err := qb.ExecuteQuery(c, dbconn, queryGelarDepan, &listGelarDepan)
if err != nil {
return listDokter
}
err = qb.ExecuteQuery(c, dbconn, queryGelarBelakang, &listGelarBelakang)
if err != nil {
return listDokter
}
mapGelarDepan := make(map[string][]string)
mapGelarBelakang := make(map[string][]string)
for _, g := range listGelarDepan {
mapGelarDepan[g.IDDokter] = append(mapGelarDepan[g.IDDokter], g.Gelar)
}
for _, g := range listGelarBelakang {
mapGelarBelakang[g.IDDokter] = append(mapGelarBelakang[g.IDDokter], g.Gelar)
}
for idx := range listDokter {
listDokter[idx].GelarDepan = mapGelarDepan[listDokter[idx].ID]
listDokter[idx].GelarBelakang = mapGelarBelakang[listDokter[idx].ID]
}
return listDokter
}
func (r dokterRepo) SearchableListDokter(c context.Context, search string, limit int, offset int) (ListDokterModelPaginate, error) {
var result ListDokterModelPaginate
@@ -128,6 +236,8 @@ func (r dokterRepo) SearchableListDokter(c context.Context, search string, limit
return result, err
}
result.Data = FetchGelar(c, r.queryBuilder, dbconn, result.Data)
return result, nil
}
+6 -1
View File
@@ -8,10 +8,15 @@ func DokterRowToResponse(row DokterModel) DokterResponse {
hfis = &row.HfisCode.String
}
namaDepan := strings.ToUpper(row.NamaDepan.String)
namaBelakang := strings.ToUpper(row.NamaBelakang.String)
gelarDepan := strings.Join(row.GelarDepan, " ")
gelarBelakang := strings.Join(row.GelarBelakang, ", ")
return DokterResponse{
ID: row.ID,
Nip: row.Nip,
NamaLengkap: strings.ToUpper(row.NamaDepan.String) + " " + strings.ToUpper(row.NamaBelakang.String),
NamaLengkap: gelarDepan + " " + namaDepan + " " + namaBelakang + " " + gelarBelakang,
HfisCode: hfis,
NamaKsm: row.NamaKsm,
}
+1 -1
View File
@@ -97,5 +97,5 @@ cd <project_name>
docker build -t antrianoperasi-api:latest .
// run docker container
docker run --env-file .env -p 8080:8080 antrianoperasi-api
docker run -d --name antrian-operasi-api --env-file .env -p 8080:8080 antrianoperasi-api:latest
```