From dcaf79af62a6f4234e26b2f4d028b0306e9c484d Mon Sep 17 00:00:00 2001 From: Yehyeok Bang Date: Tue, 23 Jan 2024 10:11:59 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[#28]=20feat:=20=EC=9E=90=EC=84=B8=20?= =?UTF-8?q?=EB=B6=84=EC=84=9D=20=EB=B3=B4=EA=B3=A0=EC=84=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 앱 캘린더에 사용할 요약 정보 조회 기능을 추가합니다. - 알림 횟수, 분석 시간, 작업 유형 필드를 추가합니다. --- app/report/controllers/report_controller.go | 90 +++++++++++++++--- app/report/models/Report.go | 11 ++- app/report/repositories/report_repository.go | 20 ++++ app/report/services/report_service.go | 97 ++++++++++++++++---- app/report/types/request_types.go | 13 ++- app/report/types/response_types.go | 14 ++- main.go | 8 +- 7 files changed, 210 insertions(+), 43 deletions(-) diff --git a/app/report/controllers/report_controller.go b/app/report/controllers/report_controller.go index 971a03d..95cd1e7 100644 --- a/app/report/controllers/report_controller.go +++ b/app/report/controllers/report_controller.go @@ -4,15 +4,16 @@ import ( "gdsc/baro/app/report/services" "gdsc/baro/app/report/types" "gdsc/baro/global" + "strconv" "github.com/gin-gonic/gin" ) type ReportController struct { - ReportService *services.ReportService + ReportService services.ReportServiceInterface } -func NewReportController(reportService *services.ReportService) *ReportController { +func NewReportController(reportService services.ReportServiceInterface) *ReportController { return &ReportController{ ReportService: reportService, } @@ -23,13 +24,13 @@ func NewReportController(reportService *services.ReportService) *ReportControlle // @Description 자세를 추정합니다. (동영상 URL을 입력받아 자세를 추정합니다.) // @Accept json // @Produce json -// @Param video_url body types.RequestPredict true "동영상 URL" +// @Param video_url body types.RequestAnalysis true "URL, 알림 횟수 등" // @Success 200 {object} global.Response // @Failure 400 {object} global.Response // @Security Bearer -// @Router /predict [post] -func (controller *ReportController) Predict(c *gin.Context) { - var input types.RequestPredict +// @Router /analysis [post] +func (controller *ReportController) Analysis(c *gin.Context) { + var input types.RequestAnalysis if err := c.ShouldBindJSON(&input); err != nil { c.JSON(400, global.Response{ Status: 400, @@ -46,7 +47,7 @@ func (controller *ReportController) Predict(c *gin.Context) { return } - response, err := controller.ReportService.Predict(c, input) + response, err := controller.ReportService.Analysis(c, input) if err != nil { c.JSON(400, global.Response{ Status: 400, @@ -70,8 +71,8 @@ func (controller *ReportController) Predict(c *gin.Context) { // @Success 200 {object} global.Response // @Failure 400 {object} global.Response // @Security Bearer -// @Router /predict [get] -func (controller *ReportController) GetPredict(c *gin.Context) { +// @Router /analysis [get] +func (controller *ReportController) GetAnalysis(c *gin.Context) { response, err := controller.ReportService.FindReportByCurrentUser(c) if err != nil { c.JSON(400, global.Response{ @@ -88,6 +89,73 @@ func (controller *ReportController) GetPredict(c *gin.Context) { }) } +// @Tags Reports +// @Summary 자세 추정 결과 id로 조회 +// @Description 보고서 id로 자세 추정 결과를 조회합니다. (요약으로 먼저 보고서 id 조회하고 사용자가 그걸 누르면 이걸 사용하기) +// @Accept json +// @Produce json +// @Param id path int true "자세 추정 결과 id" +// @Success 200 {object} global.Response +// @Failure 400 {object} global.Response +// @Security Bearer +// @Router /analysis/{id} [get] +func (controller *ReportController) GetAnalysisById(c *gin.Context) { + idStr := c.Param("id") + + id, err := strconv.ParseUint(idStr, 10, 32) + if err != nil { + c.JSON(400, global.Response{ + Status: 400, + Message: "Invalid ID", + }) + return + } + + response, err := controller.ReportService.FindById(c, uint(id)) + if err != nil { + c.JSON(400, global.Response{ + Status: 400, + Message: err.Error(), + }) + return + } + + c.JSON(200, global.Response{ + Status: 200, + Message: "success", + Data: response, + }) +} + +// @Tags Reports +// @Summary 자세 추정 결과 월별 요약 조회 +// @Description 로그인한 사용자의 자세 추정 결과를 월별로 요약하여 조회합니다. (캘린더 점 찍는 용도로 사용) +// @Accept json +// @Produce json +// @Param ym query string true "조회할 년월 (YYYYMM) 예시: 202401 (2024년 1월)" +// @Success 200 {object} global.Response +// @Failure 400 {object} global.Response +// @Security Bearer +// @Router /analysis/summary [get] +func (controller *ReportController) GetAnalysisSummary(c *gin.Context) { + yearAndMonth := c.Query("ym") + + response, err := controller.ReportService.FindReportSummaryByMonth(c, yearAndMonth) + if err != nil { + c.JSON(400, global.Response{ + Status: 400, + Message: err.Error(), + }) + return + } + + c.JSON(200, global.Response{ + Status: 200, + Message: "success", + Data: response, + }) +} + // @Tags Reports // @Summary 자세 추정 결과 전체 조회 (테스트용) // @Description 자세 추정 결과를 조회합니다. @@ -96,8 +164,8 @@ func (controller *ReportController) GetPredict(c *gin.Context) { // @Success 200 {object} global.Response // @Failure 400 {object} global.Response // @Security Bearer -// @Router /predict/all [get] -func (controller *ReportController) GetPredicts(c *gin.Context) { +// @Router /analysis/all [get] +func (controller *ReportController) GetAnalyzes(c *gin.Context) { response, err := controller.ReportService.FindAll() if err != nil { c.JSON(400, global.Response{ diff --git a/app/report/models/Report.go b/app/report/models/Report.go index 0671e9b..e29222f 100644 --- a/app/report/models/Report.go +++ b/app/report/models/Report.go @@ -3,8 +3,11 @@ package models import "time" type Report struct { - ID uint `gorm:"primaryKey"` - UserID uint - Predict string - CreatedAt time.Time `gorm:"autoCreateTime"` + ID uint `gorm:"primaryKey"` + UserID uint + AlertCount uint + AnalysisTime uint + Type string + Predict string + CreatedAt time.Time `gorm:"autoCreateTime"` } diff --git a/app/report/repositories/report_repository.go b/app/report/repositories/report_repository.go index 9cc817c..2bd9cf9 100644 --- a/app/report/repositories/report_repository.go +++ b/app/report/repositories/report_repository.go @@ -6,6 +6,14 @@ import ( "gorm.io/gorm" ) +type ReportRepositoryInterface interface { + Save(report *models.Report) error + FindByUserID(userID uint) ([]models.Report, error) + FindById(id uint) (models.Report, error) + FindByYearAndMonth(userID uint, month string) ([]models.Report, error) + FindAll() ([]models.Report, error) +} + type ReportRepository struct { DB *gorm.DB } @@ -29,6 +37,18 @@ func (repo *ReportRepository) FindByUserID(userID uint) ([]models.Report, error) return reports, result.Error } +func (repo *ReportRepository) FindById(id uint) (models.Report, error) { + var report models.Report + result := repo.DB.Where("id = ?", id).First(&report) + return report, result.Error +} + +func (repo *ReportRepository) FindByYearAndMonth(userID uint, yearAndMonth string) ([]models.Report, error) { + var reports []models.Report + result := repo.DB.Where("user_id = ? AND DATE_FORMAT(created_at, '%Y%m') = ?", userID, yearAndMonth).Find(&reports) + return reports, result.Error +} + func (repo *ReportRepository) FindAll() ([]models.Report, error) { var reports []models.Report result := repo.DB.Find(&reports) diff --git a/app/report/services/report_service.go b/app/report/services/report_service.go index d267628..cdfd6c4 100644 --- a/app/report/services/report_service.go +++ b/app/report/services/report_service.go @@ -16,29 +16,37 @@ import ( "golang.org/x/net/html" ) +type ReportServiceInterface interface { + Analysis(c *gin.Context, input types.RequestAnalysis) (string, error) + FindReportByCurrentUser(c *gin.Context) ([]types.ResponseReport, error) + FindById(c *gin.Context, id uint) (types.ResponseReport, error) + FindReportSummaryByMonth(c *gin.Context, yearAndMonth string) ([]types.ResponseReportSummary, error) + FindAll() ([]types.ResponseReport, error) +} + type ReportService struct { - ReportRepository *repositories.ReportRepository - UserUtil *utils.UserUtil + ReportRepository repositories.ReportRepositoryInterface + UserUtil utils.UserUtilInterface } -func NewReportService(reportRepository *repositories.ReportRepository, userUtil *utils.UserUtil) *ReportService { +func NewReportService(reportRepository repositories.ReportRepositoryInterface, userUtil utils.UserUtilInterface) *ReportService { return &ReportService{ ReportRepository: reportRepository, UserUtil: userUtil, } } -func (service *ReportService) Predict(c *gin.Context, input types.RequestPredict) (string, error) { +func (service *ReportService) Analysis(c *gin.Context, input types.RequestAnalysis) (string, error) { user, err := service.UserUtil.FindCurrentUser(c) if err != nil { - return "", err + return "Not Found User", err } REQUEST_URL := os.Getenv("AI_SERVER_API_URL") u, err := url.Parse(REQUEST_URL) if err != nil { - return "", err + return "Not Found AI Server", err } q := u.Query() @@ -70,7 +78,10 @@ func (service *ReportService) Predict(c *gin.Context, input types.RequestPredict } report := models.Report{ - UserID: user.ID, + UserID: user.ID, + AlertCount: input.AlertCount, + AnalysisTime: input.AnalysisTime, + Type: input.Type, } // TODO: refactor, AI Server Change to return JSON @@ -99,7 +110,7 @@ func (service *ReportService) Predict(c *gin.Context, input types.RequestPredict return message, nil } -func (service *ReportService) FindReportByCurrentUser(c *gin.Context) ([]types.ResponsePredict, error) { +func (service *ReportService) FindReportByCurrentUser(c *gin.Context) ([]types.ResponseReport, error) { user, err := service.UserUtil.FindCurrentUser(c) if err != nil { return nil, err @@ -110,12 +121,57 @@ func (service *ReportService) FindReportByCurrentUser(c *gin.Context) ([]types.R return nil, err } - var responseReports []types.ResponsePredict + var responseReports []types.ResponseReport + for _, report := range reports { + responseReport := types.ResponseReport{ + ID: report.ID, + UserID: report.UserID, + AlertCount: report.AlertCount, + AnalysisTime: report.AnalysisTime, + Predict: report.Predict, + Type: report.Type, + CreatedAt: report.CreatedAt, + } + responseReports = append(responseReports, responseReport) + } + + return responseReports, nil +} + +func (service *ReportService) FindById(c *gin.Context, id uint) (types.ResponseReport, error) { + report, err := service.ReportRepository.FindById(id) + if err != nil { + return types.ResponseReport{}, err + } + + responseReport := types.ResponseReport{ + ID: report.ID, + UserID: report.UserID, + AlertCount: report.AlertCount, + AnalysisTime: report.AnalysisTime, + Predict: report.Predict, + Type: report.Type, + CreatedAt: report.CreatedAt, + } + + return responseReport, nil +} + +func (service *ReportService) FindReportSummaryByMonth(c *gin.Context, yearAndMonth string) ([]types.ResponseReportSummary, error) { + user, err := service.UserUtil.FindCurrentUser(c) + if err != nil { + return nil, err + } + + reports, err := service.ReportRepository.FindByYearAndMonth(user.ID, yearAndMonth) + if err != nil { + return nil, err + } + + var responseReports []types.ResponseReportSummary for _, report := range reports { - responseReport := types.ResponsePredict{ + responseReport := types.ResponseReportSummary{ ID: report.ID, - UserID: report.UserID, - Predict: report.Predict, CreatedAt: report.CreatedAt, } responseReports = append(responseReports, responseReport) @@ -124,19 +180,22 @@ func (service *ReportService) FindReportByCurrentUser(c *gin.Context) ([]types.R return responseReports, nil } -func (service *ReportService) FindAll() ([]types.ResponsePredict, error) { +func (service *ReportService) FindAll() ([]types.ResponseReport, error) { reports, err := service.ReportRepository.FindAll() if err != nil { return nil, err } - var responseReports []types.ResponsePredict + var responseReports []types.ResponseReport for _, report := range reports { - responseReport := types.ResponsePredict{ - ID: report.ID, - UserID: report.UserID, - Predict: report.Predict, - CreatedAt: report.CreatedAt, + responseReport := types.ResponseReport{ + ID: report.ID, + UserID: report.UserID, + AlertCount: report.AlertCount, + AnalysisTime: report.AnalysisTime, + Predict: report.Predict, + Type: report.Type, + CreatedAt: report.CreatedAt, } responseReports = append(responseReports, responseReport) } diff --git a/app/report/types/request_types.go b/app/report/types/request_types.go index 86b6c61..1769bf9 100644 --- a/app/report/types/request_types.go +++ b/app/report/types/request_types.go @@ -8,10 +8,17 @@ func init() { validate = validator.New() } -type RequestPredict struct { - VideoURL string `json:"video_url" validate:"required"` +type RequestAnalysis struct { + VideoURL string `json:"video_url" validate:"required"` + AlertCount uint `json:"alert_count" validate:"required"` + AnalysisTime uint `json:"analysis_time" validate:"required"` + Type string `json:"type" validate:"required"` } -func (r *RequestPredict) Validate() error { +type RequestReportSummary struct { + YearAndMonth string `json:"year_and_month" validate:"required"` +} + +func (r *RequestAnalysis) Validate() error { return validate.Struct(r) } diff --git a/app/report/types/response_types.go b/app/report/types/response_types.go index 3e8907b..d69d481 100644 --- a/app/report/types/response_types.go +++ b/app/report/types/response_types.go @@ -2,9 +2,17 @@ package types import "time" -type ResponsePredict struct { +type ResponseReportSummary struct { ID uint `json:"id"` - UserID uint `json:"user_id"` - Predict string `json:"predict"` CreatedAt time.Time `json:"created_at"` } + +type ResponseReport struct { + ID uint `json:"id"` + UserID uint `json:"user_id"` + AlertCount uint `json:"alert_count"` + AnalysisTime uint `json:"analysis_time"` + Predict string `json:"predict"` + Type string `json:"type"` + CreatedAt time.Time `json:"created_at"` +} diff --git a/main.go b/main.go index 9fb8ea9..355b688 100644 --- a/main.go +++ b/main.go @@ -102,9 +102,11 @@ func (app *App) InitRouter() { secureAPI.PUT("/users/me", func(c *gin.Context) { app.UserCtrl.UpdateUserInfo(c) }) secureAPI.DELETE("/users/me", func(c *gin.Context) { app.UserCtrl.DeleteUser(c) }) - secureAPI.POST("/predict", func(c *gin.Context) { app.ReportCtrl.Predict(c) }) - secureAPI.GET("/predict", func(c *gin.Context) { app.ReportCtrl.GetPredict(c) }) - secureAPI.GET("/predict/all", func(c *gin.Context) { app.ReportCtrl.GetPredicts(c) }) + secureAPI.POST("/analysis", func(c *gin.Context) { app.ReportCtrl.Analysis(c) }) + secureAPI.GET("/analysis", func(c *gin.Context) { app.ReportCtrl.GetAnalysis(c) }) + secureAPI.GET("/analysis/:id", func(c *gin.Context) { app.ReportCtrl.GetAnalysisById(c) }) + secureAPI.GET("/analysis/summary", func(c *gin.Context) { app.ReportCtrl.GetAnalysisSummary(c) }) + secureAPI.GET("/analysis/all", func(c *gin.Context) { app.ReportCtrl.GetAnalyzes(c) }) } } From 0af5d01adee3e23562dd62a5c76046ba9920b9e9 Mon Sep 17 00:00:00 2001 From: Yehyeok Bang Date: Tue, 23 Jan 2024 10:14:27 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[#28]=20docs:=20=EC=9E=90=EC=84=B8=20?= =?UTF-8?q?=EB=B6=84=EC=84=9D=20=EB=B3=B4=EA=B3=A0=EC=84=9C=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20API=20=EB=AC=B8=EC=84=9C=20=EC=B5=9C=EC=8B=A0?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/docs.go | 180 +++++++++++++++++++++++++++++++++++----------- docs/swagger.json | 180 +++++++++++++++++++++++++++++++++++----------- docs/swagger.yaml | 131 ++++++++++++++++++++++++--------- 3 files changed, 375 insertions(+), 116 deletions(-) diff --git a/docs/docs.go b/docs/docs.go index 6ecc1d5..a17f48d 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -15,9 +15,14 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/health": { + "/analysis": { "get": { - "description": "서버가 정상 작동 중인지 확인합니다.", + "security": [ + { + "Bearer": [] + } + ], + "description": "로그인한 사용자의 자세 추정 결과를 조회합니다.", "consumes": [ "application/json" ], @@ -25,22 +30,31 @@ const docTemplate = `{ "application/json" ], "tags": [ - "HealthCheck" + "Reports" ], - "summary": "서버 상태 확인", + "summary": "자세 추정 결과 조회", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/global.Response" } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/global.Response" + } } } - } - }, - "/login": { + }, "post": { - "description": "토큰을 반환합니다. (첫 로그인 시 회원가입이 진행 후 토큰을 반환합니다.)", + "security": [ + { + "Bearer": [] + } + ], + "description": "자세를 추정합니다. (동영상 URL을 입력받아 자세를 추정합니다.)", "consumes": [ "application/json" ], @@ -48,17 +62,17 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Users" + "Reports" ], - "summary": "로그인 (첫 로그인 시 회원가입)", + "summary": "자세 추정 요청", "parameters": [ { - "description": "사용자 정보", - "name": "user", + "description": "동영상 URL", + "name": "video_url", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/types.RequestCreateUser" + "$ref": "#/definitions/types.RequestAnalysis" } } ], @@ -78,14 +92,14 @@ const docTemplate = `{ } } }, - "/predict": { + "/analysis/all": { "get": { "security": [ { "Bearer": [] } ], - "description": "로그인한 사용자의 자세 추정 결과를 조회합니다.", + "description": "자세 추정 결과를 조회합니다.", "consumes": [ "application/json" ], @@ -95,7 +109,7 @@ const docTemplate = `{ "tags": [ "Reports" ], - "summary": "자세 추정 결과 조회", + "summary": "자세 추정 결과 전체 조회 (테스트용)", "responses": { "200": { "description": "OK", @@ -110,14 +124,16 @@ const docTemplate = `{ } } } - }, - "post": { + } + }, + "/analysis/summary": { + "get": { "security": [ { "Bearer": [] } ], - "description": "자세를 추정합니다. (동영상 URL을 입력받아 자세를 추정합니다.)", + "description": "로그인한 사용자의 자세 추정 결과를 월별로 요약하여 조회합니다.", "consumes": [ "application/json" ], @@ -127,16 +143,14 @@ const docTemplate = `{ "tags": [ "Reports" ], - "summary": "자세 추정 요청", + "summary": "자세 추정 결과 월별 요약 조회", "parameters": [ { - "description": "동영상 URL", - "name": "video_url", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/types.RequestPredict" - } + "type": "string", + "description": "조회할 년월 (YYYYMM)", + "name": "ym", + "in": "query", + "required": true } ], "responses": { @@ -155,14 +169,14 @@ const docTemplate = `{ } } }, - "/predict/all": { + "/analysis/{id}": { "get": { "security": [ { "Bearer": [] } ], - "description": "자세 추정 결과를 조회합니다.", + "description": "보고서 id로 자세 추정 결과를 조회합니다.", "consumes": [ "application/json" ], @@ -172,7 +186,79 @@ const docTemplate = `{ "tags": [ "Reports" ], - "summary": "자세 추정 결과 전체 조회 (테스트용)", + "summary": "자세 추정 결과 id로 조회", + "parameters": [ + { + "type": "integer", + "description": "자세 추정 결과 id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/global.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/global.Response" + } + } + } + } + }, + "/health": { + "get": { + "description": "서버가 정상 작동 중인지 확인합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "HealthCheck" + ], + "summary": "서버 상태 확인", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/global.Response" + } + } + } + } + }, + "/login": { + "post": { + "description": "토큰을 반환합니다. (첫 로그인 시 회원가입이 진행 후 토큰을 반환합니다.)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "로그인 (첫 로그인 시 회원가입)", + "parameters": [ + { + "description": "사용자 정보", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.RequestCreateUser" + } + } + ], "responses": { "200": { "description": "OK", @@ -367,34 +453,46 @@ const docTemplate = `{ } } }, - "types.RequestCreateUser": { + "types.RequestAnalysis": { "type": "object", "required": [ - "email", - "name" + "alert_count", + "analysis_time", + "type", + "video_url" ], "properties": { - "age": { + "alert_count": { "type": "integer" }, - "email": { - "type": "string" + "analysis_time": { + "type": "integer" }, - "gender": { + "type": { "type": "string" }, - "name": { + "video_url": { "type": "string" } } }, - "types.RequestPredict": { + "types.RequestCreateUser": { "type": "object", "required": [ - "video_url" + "email", + "name" ], "properties": { - "video_url": { + "age": { + "type": "integer" + }, + "email": { + "type": "string" + }, + "gender": { + "type": "string" + }, + "name": { "type": "string" } } diff --git a/docs/swagger.json b/docs/swagger.json index a8ab37f..fe88829 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -4,9 +4,14 @@ "contact": {} }, "paths": { - "/health": { + "/analysis": { "get": { - "description": "서버가 정상 작동 중인지 확인합니다.", + "security": [ + { + "Bearer": [] + } + ], + "description": "로그인한 사용자의 자세 추정 결과를 조회합니다.", "consumes": [ "application/json" ], @@ -14,22 +19,31 @@ "application/json" ], "tags": [ - "HealthCheck" + "Reports" ], - "summary": "서버 상태 확인", + "summary": "자세 추정 결과 조회", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/global.Response" } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/global.Response" + } } } - } - }, - "/login": { + }, "post": { - "description": "토큰을 반환합니다. (첫 로그인 시 회원가입이 진행 후 토큰을 반환합니다.)", + "security": [ + { + "Bearer": [] + } + ], + "description": "자세를 추정합니다. (동영상 URL을 입력받아 자세를 추정합니다.)", "consumes": [ "application/json" ], @@ -37,17 +51,17 @@ "application/json" ], "tags": [ - "Users" + "Reports" ], - "summary": "로그인 (첫 로그인 시 회원가입)", + "summary": "자세 추정 요청", "parameters": [ { - "description": "사용자 정보", - "name": "user", + "description": "동영상 URL", + "name": "video_url", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/types.RequestCreateUser" + "$ref": "#/definitions/types.RequestAnalysis" } } ], @@ -67,14 +81,14 @@ } } }, - "/predict": { + "/analysis/all": { "get": { "security": [ { "Bearer": [] } ], - "description": "로그인한 사용자의 자세 추정 결과를 조회합니다.", + "description": "자세 추정 결과를 조회합니다.", "consumes": [ "application/json" ], @@ -84,7 +98,7 @@ "tags": [ "Reports" ], - "summary": "자세 추정 결과 조회", + "summary": "자세 추정 결과 전체 조회 (테스트용)", "responses": { "200": { "description": "OK", @@ -99,14 +113,16 @@ } } } - }, - "post": { + } + }, + "/analysis/summary": { + "get": { "security": [ { "Bearer": [] } ], - "description": "자세를 추정합니다. (동영상 URL을 입력받아 자세를 추정합니다.)", + "description": "로그인한 사용자의 자세 추정 결과를 월별로 요약하여 조회합니다.", "consumes": [ "application/json" ], @@ -116,16 +132,14 @@ "tags": [ "Reports" ], - "summary": "자세 추정 요청", + "summary": "자세 추정 결과 월별 요약 조회", "parameters": [ { - "description": "동영상 URL", - "name": "video_url", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/types.RequestPredict" - } + "type": "string", + "description": "조회할 년월 (YYYYMM)", + "name": "ym", + "in": "query", + "required": true } ], "responses": { @@ -144,14 +158,14 @@ } } }, - "/predict/all": { + "/analysis/{id}": { "get": { "security": [ { "Bearer": [] } ], - "description": "자세 추정 결과를 조회합니다.", + "description": "보고서 id로 자세 추정 결과를 조회합니다.", "consumes": [ "application/json" ], @@ -161,7 +175,79 @@ "tags": [ "Reports" ], - "summary": "자세 추정 결과 전체 조회 (테스트용)", + "summary": "자세 추정 결과 id로 조회", + "parameters": [ + { + "type": "integer", + "description": "자세 추정 결과 id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/global.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/global.Response" + } + } + } + } + }, + "/health": { + "get": { + "description": "서버가 정상 작동 중인지 확인합니다.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "HealthCheck" + ], + "summary": "서버 상태 확인", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/global.Response" + } + } + } + } + }, + "/login": { + "post": { + "description": "토큰을 반환합니다. (첫 로그인 시 회원가입이 진행 후 토큰을 반환합니다.)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "로그인 (첫 로그인 시 회원가입)", + "parameters": [ + { + "description": "사용자 정보", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/types.RequestCreateUser" + } + } + ], "responses": { "200": { "description": "OK", @@ -356,34 +442,46 @@ } } }, - "types.RequestCreateUser": { + "types.RequestAnalysis": { "type": "object", "required": [ - "email", - "name" + "alert_count", + "analysis_time", + "type", + "video_url" ], "properties": { - "age": { + "alert_count": { "type": "integer" }, - "email": { - "type": "string" + "analysis_time": { + "type": "integer" }, - "gender": { + "type": { "type": "string" }, - "name": { + "video_url": { "type": "string" } } }, - "types.RequestPredict": { + "types.RequestCreateUser": { "type": "object", "required": [ - "video_url" + "email", + "name" ], "properties": { - "video_url": { + "age": { + "type": "integer" + }, + "email": { + "type": "string" + }, + "gender": { + "type": "string" + }, + "name": { "type": "string" } } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index cf9ffae..6f21292 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -7,6 +7,22 @@ definitions: status: type: integer type: object + types.RequestAnalysis: + properties: + alert_count: + type: integer + analysis_time: + type: integer + type: + type: string + video_url: + type: string + required: + - alert_count + - analysis_time + - type + - video_url + type: object types.RequestCreateUser: properties: age: @@ -21,13 +37,6 @@ definitions: - email - name type: object - types.RequestPredict: - properties: - video_url: - type: string - required: - - video_url - type: object types.RequestUpdateUser: properties: age: @@ -40,11 +49,11 @@ definitions: info: contact: {} paths: - /health: + /analysis: get: consumes: - application/json - description: 서버가 정상 작동 중인지 확인합니다. + description: 로그인한 사용자의 자세 추정 결과를 조회합니다. produces: - application/json responses: @@ -52,21 +61,26 @@ paths: description: OK schema: $ref: '#/definitions/global.Response' - summary: 서버 상태 확인 + "400": + description: Bad Request + schema: + $ref: '#/definitions/global.Response' + security: + - Bearer: [] + summary: 자세 추정 결과 조회 tags: - - HealthCheck - /login: + - Reports post: consumes: - application/json - description: 토큰을 반환합니다. (첫 로그인 시 회원가입이 진행 후 토큰을 반환합니다.) + description: 자세를 추정합니다. (동영상 URL을 입력받아 자세를 추정합니다.) parameters: - - description: 사용자 정보 + - description: 동영상 URL in: body - name: user + name: video_url required: true schema: - $ref: '#/definitions/types.RequestCreateUser' + $ref: '#/definitions/types.RequestAnalysis' produces: - application/json responses: @@ -78,14 +92,22 @@ paths: description: Bad Request schema: $ref: '#/definitions/global.Response' - summary: 로그인 (첫 로그인 시 회원가입) + security: + - Bearer: [] + summary: 자세 추정 요청 tags: - - Users - /predict: + - Reports + /analysis/{id}: get: consumes: - application/json - description: 로그인한 사용자의 자세 추정 결과를 조회합니다. + description: 보고서 id로 자세 추정 결과를 조회합니다. + parameters: + - description: 자세 추정 결과 id + in: path + name: id + required: true + type: integer produces: - application/json responses: @@ -99,20 +121,14 @@ paths: $ref: '#/definitions/global.Response' security: - Bearer: [] - summary: 자세 추정 결과 조회 + summary: 자세 추정 결과 id로 조회 tags: - Reports - post: + /analysis/all: + get: consumes: - application/json - description: 자세를 추정합니다. (동영상 URL을 입력받아 자세를 추정합니다.) - parameters: - - description: 동영상 URL - in: body - name: video_url - required: true - schema: - $ref: '#/definitions/types.RequestPredict' + description: 자세 추정 결과를 조회합니다. produces: - application/json responses: @@ -126,14 +142,20 @@ paths: $ref: '#/definitions/global.Response' security: - Bearer: [] - summary: 자세 추정 요청 + summary: 자세 추정 결과 전체 조회 (테스트용) tags: - Reports - /predict/all: + /analysis/summary: get: consumes: - application/json - description: 자세 추정 결과를 조회합니다. + description: 로그인한 사용자의 자세 추정 결과를 월별로 요약하여 조회합니다. + parameters: + - description: 조회할 년월 (YYYYMM) + in: query + name: ym + required: true + type: string produces: - application/json responses: @@ -147,9 +169,50 @@ paths: $ref: '#/definitions/global.Response' security: - Bearer: [] - summary: 자세 추정 결과 전체 조회 (테스트용) + summary: 자세 추정 결과 월별 요약 조회 tags: - Reports + /health: + get: + consumes: + - application/json + description: 서버가 정상 작동 중인지 확인합니다. + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/global.Response' + summary: 서버 상태 확인 + tags: + - HealthCheck + /login: + post: + consumes: + - application/json + description: 토큰을 반환합니다. (첫 로그인 시 회원가입이 진행 후 토큰을 반환합니다.) + parameters: + - description: 사용자 정보 + in: body + name: user + required: true + schema: + $ref: '#/definitions/types.RequestCreateUser' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/global.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/global.Response' + summary: 로그인 (첫 로그인 시 회원가입) + tags: + - Users /users/me: delete: consumes: