diff --git a/docs/docs.go b/docs/docs.go index d7a8e6e..94b6310 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -136,6 +136,31 @@ const docTemplate = `{ } } }, + "/dashboard/antrian-per-spesialis/": { + "get": { + "tags": [ + "Dashboard" + ], + "summary": "Get Antrian Per Spesialis", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/dashboard.AntrianPerSpesialisResponse" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/shared.BaseErrorResponse" + } + } + } + } + }, "/reference/diagnosa/": { "get": { "tags": [ @@ -626,6 +651,40 @@ const docTemplate = `{ } } }, + "dashboard.AntrianPerSpesialisResponse": { + "type": "object", + "properties": { + "idSpesialis": { + "type": "integer" + }, + "jmlAntrian": { + "type": "integer" + }, + "spesialis": { + "type": "string" + }, + "subSpesialis": { + "type": "array", + "items": { + "$ref": "#/definitions/dashboard.AntrianPerSubSpesialisResponse" + } + } + } + }, + "dashboard.AntrianPerSubSpesialisResponse": { + "type": "object", + "properties": { + "idSubSpesialis": { + "type": "integer" + }, + "jmlAntrian": { + "type": "integer" + }, + "subSpesialis": { + "type": "string" + } + } + }, "diagnosa.DiagnosaResponse": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index 33979fe..7a45fe8 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -130,6 +130,31 @@ } } }, + "/dashboard/antrian-per-spesialis/": { + "get": { + "tags": [ + "Dashboard" + ], + "summary": "Get Antrian Per Spesialis", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/dashboard.AntrianPerSpesialisResponse" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/shared.BaseErrorResponse" + } + } + } + } + }, "/reference/diagnosa/": { "get": { "tags": [ @@ -620,6 +645,40 @@ } } }, + "dashboard.AntrianPerSpesialisResponse": { + "type": "object", + "properties": { + "idSpesialis": { + "type": "integer" + }, + "jmlAntrian": { + "type": "integer" + }, + "spesialis": { + "type": "string" + }, + "subSpesialis": { + "type": "array", + "items": { + "$ref": "#/definitions/dashboard.AntrianPerSubSpesialisResponse" + } + } + } + }, + "dashboard.AntrianPerSubSpesialisResponse": { + "type": "object", + "properties": { + "idSubSpesialis": { + "type": "integer" + }, + "jmlAntrian": { + "type": "integer" + }, + "subSpesialis": { + "type": "string" + } + } + }, "diagnosa.DiagnosaResponse": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 14badf1..38e61da 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -158,6 +158,28 @@ definitions: kategori: type: string type: object + dashboard.AntrianPerSpesialisResponse: + properties: + idSpesialis: + type: integer + jmlAntrian: + type: integer + spesialis: + type: string + subSpesialis: + items: + $ref: '#/definitions/dashboard.AntrianPerSubSpesialisResponse' + type: array + type: object + dashboard.AntrianPerSubSpesialisResponse: + properties: + idSubSpesialis: + type: integer + jmlAntrian: + type: integer + subSpesialis: + type: string + type: object diagnosa.DiagnosaResponse: properties: keterangan: @@ -375,6 +397,22 @@ paths: summary: Get Antrian Per Kategori tags: - Dashboard + /dashboard/antrian-per-spesialis/: + get: + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/dashboard.AntrianPerSpesialisResponse' + type: array + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/shared.BaseErrorResponse' + summary: Get Antrian Per Spesialis + tags: + - Dashboard /reference/diagnosa/: get: parameters: diff --git a/internal/domain/dashboard/handler.go b/internal/domain/dashboard/handler.go index 927117e..6f2ed7d 100644 --- a/internal/domain/dashboard/handler.go +++ b/internal/domain/dashboard/handler.go @@ -38,3 +38,29 @@ func (h DashboardHandler) GetAntrianPerKategori(c *gin.Context) { c.JSON(http.StatusOK, response) } + +// GetAntrianPerSpesialis godoc +// @Summary Get Antrian Per Spesialis +// @Tags Dashboard +// @Success 200 {object} []AntrianPerSpesialisResponse +// @Failure 500 {object} shared.BaseErrorResponse +// @Router /dashboard/antrian-per-spesialis/ [get] +func (h DashboardHandler) GetAntrianPerSpesialis(c *gin.Context) { + data, err := h.repo.GetAntrianPerSpesialis(c) + if err != nil { + errorResponse := baseResponse.BaseErrorResponse{ + Success: false, + Code: 500, + Message: err.Error(), + } + c.JSON(http.StatusInternalServerError, errorResponse) + } + + response := baseResponse.ToBaseResponse( + data.ParseToResponse(), + true, + 200, + "success get jumlah antrian per spesialis") + + c.JSON(http.StatusOK, response) +} diff --git a/internal/domain/dashboard/model.go b/internal/domain/dashboard/model.go index 3e32f54..5bc36d1 100644 --- a/internal/domain/dashboard/model.go +++ b/internal/domain/dashboard/model.go @@ -5,3 +5,64 @@ type AntrianPerKategori struct { Kategori string `db:"Kategori" json:"kategori"` JmlAntrian int `db:"jumlah_antrean" json:"jumlah_antrean"` } + +type AntrianPerSpesialisModel struct { + IdSpesialis int `db:"id_spesialis"` + Spesialis string `db:"Spesialis"` + IdSubSpesialis int `db:"id_subspesialis"` + SubSpesialis string `db:"Subspesialis"` + JmlAntrian int `db:"jml_antrian"` +} + +type AntrianPerSpesialisResponse struct { + IdSpesialis int + Spesialis string + JmlAntrian int + SubSpesialis []AntrianPerSubSpesialisResponse +} + +type AntrianPerSubSpesialisResponse struct { + IdSubSpesialis int + SubSpesialis string + JmlAntrian int +} + +type ListModelAntrianPerSpesialis []AntrianPerSpesialisModel + +func (list ListModelAntrianPerSpesialis) ParseToResponse() []AntrianPerSpesialisResponse { + resultMap := make(map[int]*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{ + IdSpesialis: item.IdSpesialis, + Spesialis: item.Spesialis, + JmlAntrian: 0, + SubSpesialis: []AntrianPerSubSpesialisResponse{}, + } + } + + // add subspesialis item + resultMap[item.IdSpesialis].SubSpesialis = append( + resultMap[item.IdSpesialis].SubSpesialis, + AntrianPerSubSpesialisResponse{ + IdSubSpesialis: item.IdSubSpesialis, + SubSpesialis: item.SubSpesialis, + JmlAntrian: item.JmlAntrian, + }, + ) + + // accumulate jmlAntrian subspesialis -> total antrian spesialis + resultMap[item.IdSpesialis].JmlAntrian += item.JmlAntrian + } + + // convert map -> slice + result := make([]AntrianPerSpesialisResponse, 0, len(resultMap)) + for _, v := range resultMap { + result = append(result, *v) + } + + return result +} diff --git a/internal/domain/dashboard/repository.go b/internal/domain/dashboard/repository.go index 918d705..41ddbc3 100644 --- a/internal/domain/dashboard/repository.go +++ b/internal/domain/dashboard/repository.go @@ -10,9 +10,11 @@ import ( const DB_NAME = "db_antrian" const TBL_NAME = "data_pasien_operasi" +const TBL_SUBSPESIALIS = "daftar_subspesialis" type IDashboardRepository interface { GetAntrianPerKategori(c *gin.Context) ([]AntrianPerKategori, error) + GetAntrianPerSpesialis(c *gin.Context) (ListModelAntrianPerSpesialis, error) } type dashboardRepo struct { @@ -85,3 +87,65 @@ func (r dashboardRepo) GetAntrianPerKategori(c *gin.Context) ([]AntrianPerKatego return result, nil } + +func (r dashboardRepo) GetAntrianPerSpesialis(c *gin.Context) (ListModelAntrianPerSpesialis, error) { + var result ListModelAntrianPerSpesialis + + query := queryUtils.DynamicQuery{ + From: TBL_SUBSPESIALIS, + Aliases: "dss", + Fields: []queryUtils.SelectField{ + {Expression: "ds.id", Alias: "id_spesialis"}, + {Expression: "dss.id", Alias: "id_subspesialis"}, + {Expression: "ds.Spesialis"}, + {Expression: "dss.Subspesialis"}, + {Expression: "COUNT(dpo.id)", Alias: "jml_antrian"}, + }, + Joins: []queryUtils.Join{ + { + Type: "LEFT", + Table: "daftar_spesialis", + Alias: "ds", + OnConditions: queryUtils.FilterGroup{ + Filters: []queryUtils.DynamicFilter{ + { + Column: "dss.FK_daftar_spesialis_ID", Operator: queryUtils.OpEqual, Value: "ds.id", + }, + }, + }, + }, + { + Type: "LEFT", + Table: "data_pasien_operasi", + Alias: "dpo", + OnConditions: queryUtils.FilterGroup{ + Filters: []queryUtils.DynamicFilter{ + { + Column: "dpo.Sub_spesialis", Operator: queryUtils.OpEqual, Value: "dss.id", + }, + { + Column: "dpo.Status_operasi", Operator: queryUtils.OpEqual, Value: "1", + }, + }, LogicOp: "AND", + }, + }, + }, + GroupBy: []string{"dss.id", "dss.Subspesialis", "ds.id", "ds.Spesialis"}, + Sort: []queryUtils.SortField{ + {Column: "ds.id"}, + }, + } + + dbconn, err := r.db.GetSQLXDB(DB_NAME) + if err != nil { + return result, err + } + + err = r.queryBuilder.ExecuteQuery( + c, dbconn, query, &result) + if err != nil { + return result, err + } + + return result, nil +} diff --git a/internal/domain/dashboard/routes.go b/internal/domain/dashboard/routes.go index 63b619a..0b1644b 100644 --- a/internal/domain/dashboard/routes.go +++ b/internal/domain/dashboard/routes.go @@ -11,4 +11,5 @@ func RegisterRoutes(r *gin.RouterGroup, dbService database.Service) { dashboardHandler := NewDashboardHandler(dashboardRepo) r.GET("/antrian-per-kategori", dashboardHandler.GetAntrianPerKategori) + r.GET("/antrian-per-spesialis", dashboardHandler.GetAntrianPerSpesialis) }