diff --git a/internal/domain/reference/dokter/handler.go b/internal/domain/reference/dokter/handler.go new file mode 100644 index 0000000..a551ff2 --- /dev/null +++ b/internal/domain/reference/dokter/handler.go @@ -0,0 +1,26 @@ +package dokter + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + +type DokterHandler struct { + repo IDokterRepository +} + +func NewDokterHandler(repo IDokterRepository) DokterHandler { + return DokterHandler{repo} +} + +func (h DokterHandler) ListDokter(c *gin.Context) { + var list ListDokterModel + + list, err := h.repo.SearchableListDokter(c) + if err != nil { + c.JSON(http.StatusInternalServerError, err) + } + + c.JSON(http.StatusOK, list.ToResponseList()) +} diff --git a/internal/domain/reference/dokter/model.go b/internal/domain/reference/dokter/model.go new file mode 100644 index 0000000..ceac45b --- /dev/null +++ b/internal/domain/reference/dokter/model.go @@ -0,0 +1,20 @@ +package dokter + +import "database/sql" + +type DokterModel struct { + ID string `json:"id" db:"id"` + Nip string `json:"nip" db:"nip"` + NamaDepan string `json:"nama_depan" db:"nama_depan"` + NamaBelakang string `json:"nama_belakang" db:"nama_belakang"` + HfisCode sql.NullString `json:"hfis_code" db:"hfis_code"` + NamaKsm string `json:"nama_ksm" db:"nama_ksm"` +} + +type DokterResponse struct { + ID string `json:"id"` + Nip string `json:"nip"` + NamaLengkap string `json:"nama_lengkap"` + HfisCode *string `json:"hfis_code"` + NamaKsm string `json:"nama_ksm"` +} diff --git a/internal/domain/reference/dokter/repository.go b/internal/domain/reference/dokter/repository.go new file mode 100644 index 0000000..f00e1cd --- /dev/null +++ b/internal/domain/reference/dokter/repository.go @@ -0,0 +1,105 @@ +package dokter + +import ( + "antrian-operasi/internal/database" + "log" + + queryUtils "antrian-operasi/internal/utils/query" + + "github.com/gin-gonic/gin" +) + +const DB_NAME = "db_antrian" + +type IDokterRepository interface { + SearchableListDokter(c *gin.Context) ([]DokterModel, error) +} + +type kategoriRepo struct { + queryBuilder *queryUtils.QueryBuilder + db database.Service +} + +func NewRepository(dbService database.Service) IDokterRepository { + queryBuilder := queryUtils.NewQueryBuilder(queryUtils.DBTypePostgreSQL). + SetAllowedColumns([]string{ + "id", + "nip", + "nama_depan", + "nama_belakang", + "hfis_code", + "nama_ksm", + }) + queryBuilder.SetSecurityOptions(false, 100) + + return kategoriRepo{ + queryBuilder: queryBuilder, + db: dbService, + } +} + +func (r kategoriRepo) SearchableListDokter(c *gin.Context) ([]DokterModel, error) { + var result []DokterModel + search := c.Query("search") + + // base query + query := queryUtils.DynamicQuery{ + From: "data_pegawai", + Aliases: "dp", + Fields: []queryUtils.SelectField{ + {Expression: "dp.id", Alias: "id"}, + {Expression: "dp.NIP", Alias: "nip"}, + {Expression: "dp.Nama_depan", Alias: "nama_depan"}, + {Expression: "dp.Nama_belakang", Alias: "nama_belakang"}, + {Expression: "HFIS_code", Alias: "hfis_code"}, + {Expression: "dk.Nama_ksm", Alias: "nama_ksm"}, + }, + } + + query.Joins = []queryUtils.Join{ + { + Type: "LEFT", + Table: "daftar_ksm", + Alias: "dk", + OnConditions: queryUtils.FilterGroup{ + Filters: []queryUtils.DynamicFilter{ + { + Column: "dk.id", Operator: queryUtils.OpEqual, Value: "dp.KSM", + }, + }, + }, + }, + } + + // filtering KSM is not null + ksmFilter := []queryUtils.DynamicFilter{ + {Column: "dp.KSM", Operator: queryUtils.OpNotNull}, + } + query.Filters = append(query.Filters, queryUtils.FilterGroup{Filters: ksmFilter, LogicOp: "AND"}) + + // TODO : build query KSM_FILTER AND (SEARCH_FILTER), current condition are all filter with OR operator + + // filtering search results + if search != "" { + searchFilters := []queryUtils.DynamicFilter{ + {Column: "dp.Nama_depan", Operator: queryUtils.OpILike, Value: "%" + search + "%"}, + {Column: "dp.NIP", Operator: queryUtils.OpILike, Value: "%" + search + "%"}, + {Column: "dp.Nama_belakang", Operator: queryUtils.OpILike, Value: "%" + search + "%"}, + {Column: "dk.Nama_ksm", Operator: queryUtils.OpILike, Value: "%" + search + "%"}, + } + query.Filters = append(query.Filters, queryUtils.FilterGroup{Filters: searchFilters, LogicOp: "OR"}) + } + + dbconn, err := r.db.GetSQLXDB(DB_NAME) + if err != nil { + log.Fatalf("unable to connect db %s", err) + } + + err = r.queryBuilder.ExecuteQuery( + c, dbconn, query, &result) + if err != nil { + log.Fatalf("unable to execute query %s", err) + } + + return result, nil +} diff --git a/internal/domain/reference/dokter/response.go b/internal/domain/reference/dokter/response.go new file mode 100644 index 0000000..2c4eeab --- /dev/null +++ b/internal/domain/reference/dokter/response.go @@ -0,0 +1,33 @@ +package dokter + +import "strings" + +func DokterRowToResponse(row DokterModel) DokterResponse { + var hfis *string + if row.HfisCode.Valid { + hfis = &row.HfisCode.String + } + + return DokterResponse{ + ID: row.ID, + Nip: row.Nip, + NamaLengkap: strings.ToUpper(row.NamaDepan) + " " + strings.ToUpper(row.NamaBelakang), + HfisCode: hfis, + NamaKsm: row.NamaKsm, + } +} + +func (d DokterModel) ToResponse() DokterResponse { + return DokterRowToResponse(d) +} + +type ListDokterModel []DokterModel + +func (rows ListDokterModel) ToResponseList() []DokterResponse { + result := make([]DokterResponse, 0, len(rows)) + for _, item := range rows { + result = append(result, item.ToResponse()) + } + + return result +} diff --git a/internal/domain/reference/dokter/routes.go b/internal/domain/reference/dokter/routes.go new file mode 100644 index 0000000..de7beb4 --- /dev/null +++ b/internal/domain/reference/dokter/routes.go @@ -0,0 +1,14 @@ +package dokter + +import ( + "antrian-operasi/internal/database" + + "github.com/gin-gonic/gin" +) + +func RegisterRoutes(r *gin.RouterGroup, dbService database.Service) { + dokterRepo := NewRepository(dbService) + dokterHandler := NewDokterHandler(dokterRepo) + + r.GET("/dokter", dokterHandler.ListDokter) +} diff --git a/internal/routes/routes.go b/internal/routes/routes.go index 5ec6e24..91aa868 100644 --- a/internal/routes/routes.go +++ b/internal/routes/routes.go @@ -3,6 +3,7 @@ package routes import ( "antrian-operasi/internal/config" "antrian-operasi/internal/database" + "antrian-operasi/internal/domain/reference/dokter" "antrian-operasi/internal/domain/reference/kategori" "antrian-operasi/internal/domain/reference/spesialis" "net/http" @@ -32,6 +33,7 @@ func RegisterRoutes(cfg *config.Config, dbService database.Service) *gin.Engine { kategori.RegisterRoutes(api, dbService) spesialis.RegisterRoutes(api, dbService) + dokter.RegisterRoutes(api, dbService) } return router