diff --git a/src/module/pendaftaran/entity/pendaftaran.go b/src/module/pendaftaran/entity/pendaftaran.go index 09e4904282236046a694b2e54ac1b0b2c65146df..c75acc7c43dc24c1dd4b98c65a0f22fc342c8cdd 100644 --- a/src/module/pendaftaran/entity/pendaftaran.go +++ b/src/module/pendaftaran/entity/pendaftaran.go @@ -49,3 +49,42 @@ type WaktuInterviewUpdateRequest struct { Id string InterviewAt time.Time } + +type RekapPendaftaran struct { + ID string `json:"pendaftaran_id"` + IDMahasiswa string `json:"mahasiswa_id"` + Nama string `json:"mahasiswa_nama"` + Nim string `json:"nim"` + Status string `json:"status"` + InterviewAt time.Time `json:"jadwal_interview"` +} + +type DetailRekapPendaftara struct { + Judul string `json:"judulTopik"` + Deskripsi string `json:"deskripsiTopik"` + InterviewAt string `json:"jadwalInterview"` + Status string `json:"status"` + WaktuPengiriman string `json:"waktuPengiriman"` + JalurPilihan string `json:"jalurPilihan"` +} + +type UpdateInterviewReq struct { + IDMahasiswa string `json:"id_mahasiswa"` + InterviewAt string `json:"interview_at"` +} + +type UpdateStatusReq struct { + IDMahasiswa string `json:"id_mahasiswa"` + Status string `json:"status"` +} + +type Stats struct { + Diterima StatsItem `json:"diterima"` + SedangProses StatsItem `json:"sedang_proses"` + Ditolak StatsItem `json:"ditolak"` +} + +type StatsItem struct { + Amount int64 `json:"amount"` + Percentage int64 `json:"percentage"` +} diff --git a/src/module/pendaftaran/internal/repository/pendaftaran.go b/src/module/pendaftaran/internal/repository/pendaftaran.go index 62c8e44eb34494ab1e6090b5d48bada20f0475e2..52c3528a898c094944971b43f791395b7a2534ae 100644 --- a/src/module/pendaftaran/internal/repository/pendaftaran.go +++ b/src/module/pendaftaran/internal/repository/pendaftaran.go @@ -152,3 +152,96 @@ func (repo *PendaftaranRepo) GetPendaftaranByPeriode(idPeriode string) (output [ } return periode, nil } + +func (repo *PendaftaranRepo) GetRekapPendaftaranDosen(idDosen string) ([]entity.RekapPendaftaran, error) { + var res []entity.RekapPendaftaran + err := repo.DBRead.Table("pendaftaran_ta"). + Select("pendaftaran_ta.id, pendaftaran_ta.id_mahasiswa, pendaftaran_ta.status, pendaftaran_ta.interview_at, pengguna.nama, pengguna.nim"). + Joins("JOIN pengguna on pendaftaran_ta.id_mahasiswa = pengguna.id"). + Where("pendaftaran_ta.id_dosen = ?", idDosen). + Scan(&res).Error + if err != nil { + return nil, err + } + + return res, nil +} + +func (repo *PendaftaranRepo) GetDetailRekapPendafataran(idDosen string, idMahasiswa string) (entity.DetailRekapPendaftara, error) { + var res entity.DetailRekapPendaftara + err := repo.DBRead.Table("topik"). + Select("topik.judul, topik.deskripsi, pendaftaran_ta.status, pendaftaran_ta.interview_at, pendaftaran_ta.waktu_pengiriman, pendaftaran_ta.jalur_pilihan"). + Joins("JOIN pendaftaran_ta ON topik.id = pendaftaran_ta.id_topik"). + Where("pendaftaran_ta.id_dosen = ? AND pendaftaran_ta.id_mahasiswa = ?", idDosen, idMahasiswa). + Scan(&res).Error + if err != nil { + return entity.DetailRekapPendaftara{}, err + } + + return res, nil +} + +func (repo *PendaftaranRepo) UpdateInterview(interviewAt string, idDosen string, idMahasiswa string) error { + updates := map[string]interface{}{ + "interview_at": interviewAt, + "status": "INTERVIEW", + } + + if err := repo.DBWrite.Table("pendaftaran_ta"). + Where("id_dosen = ? AND id_mahasiswa = ?", idDosen, idMahasiswa). + Updates(updates).Error; err != nil { + return err + } + + return nil +} + +func (repo *PendaftaranRepo) UpdateStatus(status string, idDosen string, idMahasiswa string) error { + updates := map[string]interface{}{ + "status": status, + } + + if err := repo.DBWrite.Table("pendaftaran_ta"). + Where("id_dosen = ? AND id_mahasiswa = ?", idDosen, idMahasiswa). + Updates(updates).Error; err != nil { + return err + } + + return nil +} + +func (repo *PendaftaranRepo) CountApproved(idDosen string) (int64, error) { + var count int64 + + if err := repo.DBRead.Table("pendaftaran_ta"). + Where("status = ? AND id_dosen = ?", "APPROVED", idDosen). + Count(&count).Error; err != nil { + return 0, err + } + + return count, nil +} +func (repo *PendaftaranRepo) CountProses(idDosen string) (int64, error) { + var count int64 + + if err := repo.DBRead.Table("pendaftaran_ta"). + Where("id_dosen = ? AND status = ? ", idDosen, "NOT_ASSIGNED"). + Or("id_dosen = ? AND status = ? ", idDosen, "INTERVIEW"). + Count(&count).Error; err != nil { + return 0, err + } + + return count, nil +} + +func (repo *PendaftaranRepo) CountRejected(idDosen string) (int64, error) { + var count int64 + + if err := repo.DBRead.Table("pendaftaran_ta"). + Where("status = ? AND id_dosen = ?", "REJECTED", idDosen). + Count(&count).Error; err != nil { + return 0, err + } + + return count, nil +} diff --git a/src/module/pendaftaran/internal/usecase/pendaftaran.go b/src/module/pendaftaran/internal/usecase/pendaftaran.go index be53ada75a1c9bb428239cb8a4911ea0c8dbfb10..109d4bd190916fed52567144eb5876180903c8de 100644 --- a/src/module/pendaftaran/internal/usecase/pendaftaran.go +++ b/src/module/pendaftaran/internal/usecase/pendaftaran.go @@ -1,6 +1,7 @@ package usecase import ( + "errors" "time" "gitlab.informatika.org/k-01-11/graduit-be/src/models" @@ -16,6 +17,11 @@ type PendaftaranUsecase interface { UpdateWaktuInterview(id string, val time.Time) (output []models.PendaftaranTA, err error) GetPendaftaranByPeriode(id string) (output []models.PendaftaranTA, err error) GetPendaftaranById(id string) (output []entity.PendaftaranGetResponse, err error) + GetRekapPendaftaranDosen(id string) ([]entity.RekapPendaftaran, error) + GetDetailRekapPendafataran(idDosen string, idMahasiswa string) (entity.DetailRekapPendaftara, error) + UpdateInterview(interviewAt string, idDosen string, idMahasiswa string) error + UpdateStatus(status string, idDosen string, idMahasiswa string) error + GetStatisticsPendaftaran(idDosen string) (entity.Stats, error) } type PendaftaranUc struct { @@ -66,3 +72,62 @@ func (uc *PendaftaranUc) GetPendaftaranByPeriode(id string) (output []models.Pen func (uc *PendaftaranUc) GetPendaftaranById(id string) (output []entity.PendaftaranGetResponse, err error) { return uc.pendaftaranRepo.GetPendaftaranById(id) } + +func (uc *PendaftaranUc) GetRekapPendaftaranDosen(id string) (output []entity.RekapPendaftaran, err error) { + return uc.pendaftaranRepo.GetRekapPendaftaranDosen(id) +} + +func (uc *PendaftaranUc) GetDetailRekapPendafataran(idDosen string, idMahasiswa string) (entity.DetailRekapPendaftara, error) { + return uc.pendaftaranRepo.GetDetailRekapPendafataran(idDosen, idMahasiswa) +} + +func (uc *PendaftaranUc) UpdateInterview(interviewAt string, idDosen string, idMahasiswa string) error { + if interviewAt == "" { + return errors.New("interview timestamp cannot be empty") + } + return uc.pendaftaranRepo.UpdateInterview(interviewAt, idDosen, idMahasiswa) +} + +func (uc *PendaftaranUc) UpdateStatus(status string, idDosen string, idMahasiswa string) error { + if status == "" { + return errors.New("interview timestamp cannot be empty") + } + return uc.pendaftaranRepo.UpdateStatus(status, idDosen, idMahasiswa) +} + +func (uc *PendaftaranUc) GetStatisticsPendaftaran(idDosen string) (entity.Stats, error) { + approved, err := uc.pendaftaranRepo.CountApproved(idDosen) + if err != nil { + return entity.Stats{}, err + } + proses, err := uc.pendaftaranRepo.CountProses(idDosen) + if err != nil { + return entity.Stats{}, err + } + rejected, err := uc.pendaftaranRepo.CountRejected(idDosen) + if err != nil { + return entity.Stats{}, err + } + total := approved + proses + rejected + percApproved := approved / total * 100 + percProses := proses / total * 100 + perRejected := rejected / total * 100 + diterima := entity.StatsItem{ + Amount: approved, + Percentage: percApproved, + } + sedangProses := entity.StatsItem{ + Amount: proses, + Percentage: percProses, + } + ditolak := entity.StatsItem{ + Amount: rejected, + Percentage: perRejected, + } + stats := entity.Stats{ + Diterima: diterima, + SedangProses: sedangProses, + Ditolak: ditolak, + } + return stats, nil +} diff --git a/src/module/pendaftaran/internal/usecase/repository.go b/src/module/pendaftaran/internal/usecase/repository.go index a647e3bf12e06407f1d2418f4e4444384a74e88c..f7a1733f46ad9821e04c66764c8c79fd11a0ebd3 100644 --- a/src/module/pendaftaran/internal/usecase/repository.go +++ b/src/module/pendaftaran/internal/usecase/repository.go @@ -16,4 +16,11 @@ type PendaftaranRepository interface { SetTimeInterview(id string, val time.Time) (output []models.PendaftaranTA, err error) GetPendaftaranByPeriode(idPeriode string) (output []models.PendaftaranTA, err error) GetPendaftaranById(id string) (output []entity.PendaftaranGetResponse, err error) + GetRekapPendaftaranDosen(idDosen string) ([]entity.RekapPendaftaran, error) + GetDetailRekapPendafataran(idDosen string, idMahasiswa string) (entity.DetailRekapPendaftara, error) + UpdateInterview(interviewAt string, idDosen string, idMahasiswa string) error + UpdateStatus(status string, idDosen string, idMahasiswa string) error + CountApproved(idDosen string) (int64, error) + CountProses(idDosen string) (int64, error) + CountRejected(idDosen string) (int64, error) } diff --git a/src/module/pendaftaran/transport/admin_handler.go b/src/module/pendaftaran/transport/admin_handler.go index 822e0f9bab736193fd13e8611a9c39a668081f34..fe8144de9130bfac5a05307d9b72d7440d63fc29 100644 --- a/src/module/pendaftaran/transport/admin_handler.go +++ b/src/module/pendaftaran/transport/admin_handler.go @@ -35,6 +35,11 @@ func (t *AdminPendaftaranHandler) MountAdmin(group *echo.Group) { group.POST("/pendaftaran-update-interview", t.UpdateWaktuInterview) group.GET("/pendaftaran-by-periode", t.GetPendaftaranByPeriode) group.GET("/pendaftaran-by-id", t.GetPendaftaranById) + group.GET("/rekap-pendaftaran", t.GetRekapPendaftaranDosen) + group.GET("/detail-rekap-pendaftaran", t.GetDetailRekapPendafataran) + group.PUT("/update-interview", t.UpdateInterview) + group.PUT("/update-status", t.UpdateStatus) + group.GET("/statistics", t.GetStatistics) } // AddPendaftaran adds a new pendaftaran record. @@ -85,8 +90,11 @@ func (t *AdminPendaftaranHandler) GetPendaftaran(c echo.Context) error { } func (t *AdminPendaftaranHandler) GetPendaftaranByIdDosen(c echo.Context) error { - id := c.QueryParam("id") - listGroupLimit, err := t.pendaftaranUsecase.GetPendaftaranByIdDosen(id) + payload, ok := c.Get("authPayload").(utils.Payload) + if !ok { + return c.JSON(http.StatusInternalServerError, utils.ResponseDetailOutput(false, http.StatusInternalServerError, "Error parsing id", nil)) + } + listGroupLimit, err := t.pendaftaranUsecase.GetPendaftaranByIdDosen(payload.ID) if err != nil { return c.JSON(http.StatusBadRequest, utils.ResponseDetailOutput(false, http.StatusBadRequest, err.Error(), nil)) } @@ -94,6 +102,80 @@ func (t *AdminPendaftaranHandler) GetPendaftaranByIdDosen(c echo.Context) error return c.JSON(http.StatusOK, utils.ResponseDetailOutput(true, http.StatusOK, "Pendaftaran successfully retreived", listGroupLimit)) } +func (t *AdminPendaftaranHandler) GetRekapPendaftaranDosen(c echo.Context) error { + payload, ok := c.Get("authPayload").(utils.Payload) + if !ok { + return c.JSON(http.StatusInternalServerError, utils.ResponseDetailOutput(false, http.StatusInternalServerError, "Error parsing id", nil)) + } + rekap, err := t.pendaftaranUsecase.GetRekapPendaftaranDosen(payload.ID) + if err != nil { + return c.JSON(http.StatusBadRequest, utils.ResponseDetailOutput(false, http.StatusBadRequest, err.Error(), nil)) + } + + return c.JSON(http.StatusOK, utils.ResponseDetailOutput(true, http.StatusOK, "Rekap successfully retreived", rekap)) +} + +func (t *AdminPendaftaranHandler) GetDetailRekapPendafataran(c echo.Context) error { + payload, ok := c.Get("authPayload").(utils.Payload) + if !ok { + return c.JSON(http.StatusInternalServerError, utils.ResponseDetailOutput(false, http.StatusInternalServerError, "Error parsing id", nil)) + } + idMahasiswa := c.QueryParam("id_mahasiswa") + rekap, err := t.pendaftaranUsecase.GetDetailRekapPendafataran(payload.ID, idMahasiswa) + if err != nil { + return c.JSON(http.StatusBadRequest, utils.ResponseDetailOutput(false, http.StatusBadRequest, err.Error(), nil)) + } + + return c.JSON(http.StatusOK, utils.ResponseDetailOutput(true, http.StatusOK, "Detial Rekap successfully retreived", rekap)) +} + +func (t *AdminPendaftaranHandler) UpdateInterview(c echo.Context) error { + payload, ok := c.Get("authPayload").(utils.Payload) + if !ok { + return c.JSON(http.StatusInternalServerError, utils.ResponseDetailOutput(false, http.StatusInternalServerError, "Error parsing id", nil)) + } + request := new(entity.UpdateInterviewReq) + if err := c.Bind(&request); err != nil { + return c.JSON(http.StatusBadRequest, utils.ResponseDetailOutput(false, http.StatusBadRequest, err.Error(), nil)) + } + err := t.pendaftaranUsecase.UpdateInterview(request.InterviewAt, payload.ID, request.IDMahasiswa) + if err != nil { + return c.JSON(http.StatusBadRequest, utils.ResponseDetailOutput(false, http.StatusBadRequest, err.Error(), nil)) + } + + return c.JSON(http.StatusOK, utils.ResponseDetailOutput(true, http.StatusOK, "Interview successfully updated", err)) +} + +func (t *AdminPendaftaranHandler) UpdateStatus(c echo.Context) error { + payload, ok := c.Get("authPayload").(utils.Payload) + if !ok { + return c.JSON(http.StatusInternalServerError, utils.ResponseDetailOutput(false, http.StatusInternalServerError, "Error parsing id", nil)) + } + request := new(entity.UpdateStatusReq) + if err := c.Bind(&request); err != nil { + return c.JSON(http.StatusBadRequest, utils.ResponseDetailOutput(false, http.StatusBadRequest, err.Error(), nil)) + } + err := t.pendaftaranUsecase.UpdateStatus(request.Status, payload.ID, request.IDMahasiswa) + if err != nil { + return c.JSON(http.StatusBadRequest, utils.ResponseDetailOutput(false, http.StatusBadRequest, err.Error(), nil)) + } + + return c.JSON(http.StatusOK, utils.ResponseDetailOutput(true, http.StatusOK, "Interview successfully updated", err)) +} + +func (t *AdminPendaftaranHandler) GetStatistics(c echo.Context) error { + payload, ok := c.Get("authPayload").(utils.Payload) + if !ok { + return c.JSON(http.StatusInternalServerError, utils.ResponseDetailOutput(false, http.StatusInternalServerError, "Error parsing id", nil)) + } + stats, err := t.pendaftaranUsecase.GetStatisticsPendaftaran(payload.ID) + if err != nil { + return c.JSON(http.StatusBadRequest, utils.ResponseDetailOutput(false, http.StatusBadRequest, err.Error(), nil)) + } + + return c.JSON(http.StatusOK, utils.ResponseDetailOutput(true, http.StatusOK, "stats successfully updated", stats)) +} + func (t *AdminPendaftaranHandler) GetPendaftaranById(c echo.Context) error { id := c.QueryParam("id") listGroupLimit, err := t.pendaftaranUsecase.GetPendaftaranById(id) diff --git a/src/module/topic_allocation/entity/topic_allocation.go b/src/module/topic_allocation/entity/topic_allocation.go index e979c6ad6364509823472a57258db30515abbf9f..9998b93918bcc06b05769b79d6af9af558429de4 100644 --- a/src/module/topic_allocation/entity/topic_allocation.go +++ b/src/module/topic_allocation/entity/topic_allocation.go @@ -1,12 +1,12 @@ package entity type Topik struct { - ID string `json:"id"` - Judul string `json:"judul"` - Deskripsi string `json:"deskripsi"` - PengajuID string `json:"pengaju"` + ID string `json:"id"` + Judul string `json:"judul"` + Deskripsi string `json:"deskripsi"` + PengajuID string `json:"pengaju_id"` - Pengguna Pengguna `gorm:"foreignKey:PengajuID"` + Pengguna Pengguna `json:"pengaju" gorm:"foreignKey:PengajuID"` } func (Topik) TableName() string { @@ -14,10 +14,10 @@ func (Topik) TableName() string { } type Pengguna struct { - ID string `gorm:"type:uuid;primaryKey" json:"id"` - Nama string `json:"nama"` - Email string `json:"email"` - Roles string `json:"roles"` + ID string `gorm:"type:uuid;primaryKey" json:"id"` + Nama string `json:"nama"` + Email string `json:"email"` + Roles string `json:"roles"` } func (Pengguna) TableName() string { @@ -25,14 +25,14 @@ func (Pengguna) TableName() string { } type GetAllReturnType struct { - DaftarTopikData []Topik `json:"data"` - MaxPage int `json:"maxPage"` + DaftarTopikData []Topik `json:"data"` + MaxPage int `json:"maxPage"` } type TopikPostPutReqData struct { Judul string `json:"judul"` Deskripsi string `json:"deskripsi"` - PengajuID string `json:"pengajuID"` + PengajuID string `json:"idPengaju"` } type ParamValues struct { diff --git a/src/module/topic_allocation/internal/repository/topic_allocation.go b/src/module/topic_allocation/internal/repository/topic_allocation.go index 79212600e4199a9b243c249fe283635bdde250a5..e6172a426658e8f2616b339f7311b32bae5f332d 100644 --- a/src/module/topic_allocation/internal/repository/topic_allocation.go +++ b/src/module/topic_allocation/internal/repository/topic_allocation.go @@ -20,10 +20,10 @@ func NewTopicAllocationRepository(dbWrite *gorm.DB, dbRead *gorm.DB) *TopicAlloc func (repo *TopicAllocationRepo) NewTopic(reqData entity.TopikPostPutReqData) (output entity.TopikPostPutReqData, err error) { topic := entity.Topik{ - ID: uuid.New().String(), - Judul: reqData.Judul, - Deskripsi: reqData.Deskripsi, - PengajuID: reqData.PengajuID, + ID: uuid.New().String(), + Judul: reqData.Judul, + Deskripsi: reqData.Deskripsi, + PengajuID: reqData.PengajuID, } result := repo.DBWrite.Create(&topic) @@ -34,7 +34,6 @@ func (repo *TopicAllocationRepo) NewTopic(reqData entity.TopikPostPutReqData) (o return reqData, nil } - func (repo *TopicAllocationRepo) GetTopic(page int, limit int, search string, id string) (output entity.GetAllReturnType, err error) { var topics []entity.Topik @@ -68,16 +67,16 @@ func (repo *TopicAllocationRepo) GetTopic(page int, limit int, search string, id } var maxPage int - + if limit == 0 || count == 0 { maxPage = 1 } else { maxPage = int(count) / limit } - data := entity.GetAllReturnType { + data := entity.GetAllReturnType{ DaftarTopikData: topics, - MaxPage: maxPage, + MaxPage: maxPage, } return data, nil @@ -112,7 +111,6 @@ func (repo *TopicAllocationRepo) UpdateTopic(reqData entity.TopikPostPutReqData, return reqData, nil } - func (repo *TopicAllocationRepo) DeleteTopic(ID string) (err error) { var topic entity.Topik diff --git a/src/module/topic_allocation/internal/usecase/repository.go b/src/module/topic_allocation/internal/usecase/repository.go index 165f98f4d5c7da042a644911c63fa3bd01cb5566..3461dcbcb787a1f13377006aaa9b74589659a458 100644 --- a/src/module/topic_allocation/internal/usecase/repository.go +++ b/src/module/topic_allocation/internal/usecase/repository.go @@ -8,4 +8,4 @@ type TopicAllocationRepo interface { GetTopicByID(ID string) (output entity.Topik, err error) UpdateTopic(topic entity.TopikPostPutReqData, id string) (output entity.TopikPostPutReqData, err error) DeleteTopic(ID string) (err error) -} \ No newline at end of file +} diff --git a/src/module/topic_allocation/internal/usecase/topic_allocation.go b/src/module/topic_allocation/internal/usecase/topic_allocation.go index 589038bf932bd38790a7cd8c463bdea25f9b8080..abebe74509fff4829efcca2b17341ae532ff7bf4 100644 --- a/src/module/topic_allocation/internal/usecase/topic_allocation.go +++ b/src/module/topic_allocation/internal/usecase/topic_allocation.go @@ -10,7 +10,7 @@ type TopicUsecase interface { GetTopic(param utils.PageLimitSearchID) (entity.GetAllReturnType, error) GetTopicByID(param string) (entity.Topik, error) UpdateTopic(topic entity.TopikPostPutReqData, id string) (entity.TopikPostPutReqData, error) - DeleteTopic(param string) (error) + DeleteTopic(param string) error } type TopicUc struct { @@ -52,7 +52,7 @@ func (uc *TopicUc) UpdateTopic(topic entity.TopikPostPutReqData, id string) (ent return updatedTopic, nil } -func (uc *TopicUc) DeleteTopic(param string) (error) { +func (uc *TopicUc) DeleteTopic(param string) error { err := uc.topicAllocationRepo.DeleteTopic(param) if err != nil { @@ -60,4 +60,4 @@ func (uc *TopicUc) DeleteTopic(param string) (error) { } return nil -} \ No newline at end of file +}