Compare commits

...
5 Commits
Author SHA1 Message Date
renaldybrada e63f78dc2f fixing sort by name spesialis 2026-02-18 15:30:08 +07:00
renaldybrada e290664ca3 fixing query nomor urut 2026-02-18 15:29:19 +07:00
renaldybrada a08a079f67 fixing no urut subspesialis not sorted 2026-02-18 14:59:32 +07:00
renaldybrada 5147bf4df3 test antrian update status 2026-02-18 13:46:27 +07:00
renaldybrada 466a1606e9 update readme 2026-02-18 13:15:55 +07:00
4 changed files with 112 additions and 13 deletions

No files matched your search

@@ -0,0 +1,64 @@
package antrianoperasi
import (
"testing"
"time"
)
type datasetUpdateStatus struct {
testContext string
request StatusPasienRequest
expected bool
}
func TestValidationUpdateStatuRequest(t *testing.T) {
testKeterangan := "test keterangan"
dataset := []datasetUpdateStatus{
{
testContext: "should error : Tanggal selesai terisi ketika status belum selesai",
request: StatusPasienRequest{
TglSelesai: &time.Time{},
StatusOperasi: "3",
KeteranganStatus: nil,
},
expected: false,
},
{
testContext: "should error : Tanggal selesai harus diisi ketika status selesai",
request: StatusPasienRequest{
TglSelesai: nil,
StatusOperasi: "2",
KeteranganStatus: &testKeterangan,
},
expected: false,
},
{
testContext: "should valid : status belum, update keterangan",
request: StatusPasienRequest{
TglSelesai: nil,
StatusOperasi: "1",
KeteranganStatus: &testKeterangan,
},
expected: true,
},
{
testContext: "should valid : status sudah, tanggal selesai not nil",
request: StatusPasienRequest{
TglSelesai: &time.Time{},
StatusOperasi: "2",
KeteranganStatus: &testKeterangan,
},
expected: true,
},
}
for _, testCase := range dataset {
t.Run(testCase.testContext, func(t *testing.T) {
isValid, errValidation := testCase.request.UpdateStatusValidation()
if isValid != testCase.expected {
t.Fatalf("test failed. expected %v, but got %v", testCase.testContext, errValidation)
}
})
}
}
@@ -48,7 +48,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_spesialis", "no_urut_sub_spesialis",
}).
SetAllowedTables([]string{TBL_NAME, TBL_DIAGNOSA_OPERASI})
queryBuilder.SetSecurityOptions(false, 100)
@@ -401,13 +401,13 @@ func (r antrianOperasiRepo) SearchableListAntrianOperasi(c *gin.Context) (ListPa
wfSpesialis := queryUtils.WindowFunction{
Function: "ROW_NUMBER",
Over: "\"dpo\".\"Kategori_operasi\", \"dpo\".\"Spesialis\"",
Over: "\"dpo\".\"Spesialis\"",
OrderBy: "\"dpo\".\"Tanggal_daftar\", \"dpo\".\"date_created\", \"dpo\".\"date_updated\"",
Alias: "no_urut_spesialis",
}
wfSubSpesialis := queryUtils.WindowFunction{
Function: "ROW_NUMBER",
Over: "\"dpo\".\"Kategori_operasi\", \"dpo\".\"Spesialis\", \"dpo\".\"Sub_spesialis\"",
Over: "\"dpo\".\"Sub_spesialis\"",
OrderBy: "\"dpo\".\"Tanggal_daftar\", \"dpo\".\"date_created\", \"dpo\".\"date_updated\"",
Alias: "no_urut_sub_spesialis",
}
+19 -9
View File
@@ -1,6 +1,9 @@
package dashboard
import "time"
import (
"sort"
"time"
)
type AntrianPerKategori struct {
IdKategori int `db:"Kategori_operasi" json:"id_kategori"`
@@ -84,13 +87,13 @@ type TableAntreanPerSubSpesialis struct {
type ListModelAntrianPerSpesialis []AntrianPerSpesialisModel
func (list ListModelAntrianPerSpesialis) ParseToResponse() []AntrianPerSpesialisResponse {
resultMap := make(map[int]*AntrianPerSpesialisResponse)
resultMap := make(map[string]*AntrianPerSpesialisResponse)
for _, item := range list {
// check if spesialis already on resultMap
// if not exist, create antrian spesialis response
if _, ok := resultMap[item.IdSpesialis]; !ok {
resultMap[item.IdSpesialis] = &AntrianPerSpesialisResponse{
if _, ok := resultMap[item.Spesialis]; !ok {
resultMap[item.Spesialis] = &AntrianPerSpesialisResponse{
IdSpesialis: item.IdSpesialis,
Spesialis: item.Spesialis,
JmlAntrian: 0,
@@ -99,8 +102,8 @@ func (list ListModelAntrianPerSpesialis) ParseToResponse() []AntrianPerSpesialis
}
// add subspesialis item
resultMap[item.IdSpesialis].SubSpesialis = append(
resultMap[item.IdSpesialis].SubSpesialis,
resultMap[item.Spesialis].SubSpesialis = append(
resultMap[item.Spesialis].SubSpesialis,
AntrianPerSubSpesialisResponse{
IdSubSpesialis: item.IdSubSpesialis,
SubSpesialis: item.SubSpesialis,
@@ -109,13 +112,20 @@ func (list ListModelAntrianPerSpesialis) ParseToResponse() []AntrianPerSpesialis
)
// accumulate jmlAntrian subspesialis -> total antrian spesialis
resultMap[item.IdSpesialis].JmlAntrian += item.JmlAntrian
resultMap[item.Spesialis].JmlAntrian += item.JmlAntrian
}
// sort by spesialis name ascending
keys := make([]string, 0, len(resultMap))
for k := range resultMap {
keys = append(keys, resultMap[k].Spesialis)
}
sort.Strings(keys)
// convert map -> slice
result := make([]AntrianPerSpesialisResponse, 0, len(resultMap))
for _, v := range resultMap {
result = append(result, *v)
for _, v := range keys {
result = append(result, *resultMap[v])
}
return result
+26 -1
View File
@@ -52,4 +52,29 @@ Pastikan sudah menulis komentar dengan format dari swagger di handler endpoint
cd <project_name>
swag init -g cmd/api/main.go -o docs
````
````
## Unit Testing
````bash
// masuk ke root project
cd <project_name>
go test -v ./internal/...
````
## Build project
````bash
// masuk ke root project
cd <project_name>
go build ./cmd/api
````
## Disabled/Enabled Keycloak Authentication
Project ini menggunakan autentikasi dengan token dari keycloak. Untuk kebutuhan debugging yang tidak membutuhkan autentikasi, keycloak dapat di-<i><b>disabled</b></i> dengan cara memberikan nilai false di file `.env` bagian `KEYCLOAK_IS_ENABLE`
```
#KEYCLOAK CREDENTIAL
..
..
KEYCLOAK_IS_ENABLE=false
```