From 2e96d6130eed1e8e58e93cce7f3aa52ab4672b24 Mon Sep 17 00:00:00 2001 From: Eraxyso <130852025+Eraxyso@users.noreply.github.com> Date: Mon, 22 Jul 2024 03:01:16 +0000 Subject: [PATCH 01/10] feat: implement GetQuestionnaireResult --- handler/questionnaire.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/handler/questionnaire.go b/handler/questionnaire.go index 729fa111..202f125c 100644 --- a/handler/questionnaire.go +++ b/handler/questionnaire.go @@ -3,6 +3,7 @@ package handler import ( "fmt" "net/http" + "time" "github.com/labstack/echo/v4" "github.com/traPtitech/anke-to/controller" @@ -173,6 +174,38 @@ func (h Handler) PostQuestionnaireResponse(ctx echo.Context, questionnaireID ope // (GET /questionnaires/{questionnaireID}/result) func (h Handler) GetQuestionnaireResult(ctx echo.Context, questionnaireID openapi.QuestionnaireIDInPath) error { res := openapi.Result{} + userID, err := getUserID(ctx) + if err != nil { + ctx.Logger().Errorf("failed to get userID: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get userID: %w", err)) + } + + params := openapi.GetQuestionnaireResponsesParams{} + q := controller.NewQuestionnaire() + responses, err := q.GetQuestionnaireResponses(ctx, questionnaireID, params, userID) + if err != nil { + ctx.Logger().Errorf("failed to get questionnaire responses: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire responses: %+w", err)) + } + + for _, response := range responses { + tmp := struct { + Body []openapi.ResponseBody `json:"body"` + IsDraft bool `json:"is_draft"` + ModifiedAt time.Time `json:"modified_at"` + QuestionnaireId int `json:"questionnaire_id"` + ResponseId int `json:"response_id"` + SubmittedAt time.Time `json:"submitted_at"` + }{ + Body: response.Body, + IsDraft: response.IsDraft, + ModifiedAt: response.ModifiedAt, + QuestionnaireId: response.QuestionnaireId, + ResponseId: response.ResponseId, + SubmittedAt: response.SubmittedAt, + } + res = append(res, tmp) + } return ctx.JSON(200, res) } From af155ecacd882ed0e929a4752defc6bba549886b Mon Sep 17 00:00:00 2001 From: Eraxyso <130852025+Eraxyso@users.noreply.github.com> Date: Mon, 12 Aug 2024 08:56:32 +0000 Subject: [PATCH 02/10] feat: implement GetMyResponses(wip) --- controller/questionnaire.go | 9 ---- controller/response.go | 103 ++++++++++++++++++++++++++++++++++++ handler/response.go | 17 +++++- model/respondents.go | 1 + model/respondents_impl.go | 19 +++++++ model/targets.go | 1 + model/targets_impl.go | 5 ++ 7 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 controller/response.go diff --git a/controller/questionnaire.go b/controller/questionnaire.go index 9ccbf238..a0ac8ce9 100644 --- a/controller/questionnaire.go +++ b/controller/questionnaire.go @@ -15,15 +15,6 @@ import ( "gopkg.in/guregu/null.v4" ) -// Response Responseの構造体 -type Response struct { - model.IQuestionnaire - model.IValidation - model.IScaleLabel - model.IRespondent - model.IResponse -} - // Questionnaire Questionnaireの構造体 type Questionnaire struct { model.IQuestionnaire diff --git a/controller/response.go b/controller/response.go new file mode 100644 index 00000000..8d2df275 --- /dev/null +++ b/controller/response.go @@ -0,0 +1,103 @@ +package controller + +import ( + "fmt" + "net/http" + "time" + + "github.com/labstack/echo/v4" + "github.com/traPtitech/anke-to/model" + "github.com/traPtitech/anke-to/openapi" +) + +// Response Responseの構造体 +type Response struct { + model.IQuestionnaire + model.IRespondent + model.ITarget +} + +func NewResponse() *Response { + return &Response{} +} + +func (r Response) GetMyResponses(ctx echo.Context, params openapi.GetMyResponsesParams, userID string) (openapi.ResponsesWithQuestionnaireInfo, error) { + res := openapi.ResponsesWithQuestionnaireInfo{} + + sort := string(*params.Sort) + responsesID := []int{} + responsesID, err := r.IRespondent.GetMyResponsesID(ctx.Request().Context(), sort, userID) + if err != nil { + ctx.Logger().Errorf("failed to get my responses ID: %+v", err) + return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire responses: %+w", err)) + } + + for _, responseID := range responsesID { + responseDetail, err := r.IRespondent.GetRespondentDetail(ctx.Request().Context(), responseID) + if err != nil { + ctx.Logger().Errorf("failed to get respondent detail: %+v", err) + return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get respondent detail: %+w", err)) + } + + questionnaire, _, _, _, _, _, err := r.IQuestionnaire.GetQuestionnaireInfo(ctx.Request().Context(), responseDetail.QuestionnaireID) + if err != nil { + ctx.Logger().Errorf("failed to get questionnaire info: %+v", err) + return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire info: %+w", err)) + } + + isTargetingMe, err := r.ITarget.IsTargetingMe(ctx.Request().Context(), responseDetail.QuestionnaireID, userID) + if err != nil { + ctx.Logger().Errorf("failed to get target info: %+v", err) + return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get target info: %+w", err)) + } + + questionnaireInfo := struct { + CreatedAt time.Time `json:"created_at"` + IsTargetingMe bool `json:"is_targeting_me"` + ModifiedAt time.Time `json:"modified_at"` + ResponseDueDateTime *time.Time `json:"response_due_date_time,omitempty"` + Title string `json:"title"` + }{ + CreatedAt: questionnaire.CreatedAt, + IsTargetingMe: isTargetingMe, + ModifiedAt: questionnaire.ModifiedAt, + ResponseDueDateTime: &questionnaire.ResTimeLimit.Time, + Title: questionnaire.Title, + } + + response, err := respondentDetail2Response(ctx, responseDetail) + if err != nil { + ctx.Logger().Errorf("failed to convert respondent detail into response: %+v", err) + return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to convert respondent detail into response: %+w", err)) + } + + tmp := struct { + Body []openapi.ResponseBody `json:"body"` + IsDraft bool `json:"is_draft"` + ModifiedAt time.Time `json:"modified_at"` + QuestionnaireId int `json:"questionnaire_id"` + QuestionnaireInfo *struct { + CreatedAt time.Time `json:"created_at"` + IsTargetingMe bool `json:"is_targeting_me"` + ModifiedAt time.Time `json:"modified_at"` + ResponseDueDateTime *time.Time `json:"response_due_date_time,omitempty"` + Title string `json:"title"` + } `json:"questionnaire_info,omitempty"` + Respondent openapi.TraqId `json:"respondent"` + ResponseId int `json:"response_id"` + SubmittedAt time.Time `json:"submitted_at"` + }{ + Body: response.Body, + IsDraft: response.IsDraft, + ModifiedAt: response.ModifiedAt, + QuestionnaireId: response.QuestionnaireId, + QuestionnaireInfo: &questionnaireInfo, + Respondent: userID, + ResponseId: response.ResponseId, + SubmittedAt: response.SubmittedAt, + } + res = append(res, tmp) + } + + return res, nil +} diff --git a/handler/response.go b/handler/response.go index 6212214f..40cbda84 100644 --- a/handler/response.go +++ b/handler/response.go @@ -1,14 +1,29 @@ package handler import ( + "fmt" + "net/http" + "github.com/labstack/echo/v4" + "github.com/traPtitech/anke-to/controller" "github.com/traPtitech/anke-to/openapi" ) // (GET /responses/myResponses) func (h Handler) GetMyResponses(ctx echo.Context, params openapi.GetMyResponsesParams) error { - res := []openapi.ResponsesWithQuestionnaireInfo{} + res := openapi.ResponsesWithQuestionnaireInfo{} + userID, err := getUserID(ctx) + if err != nil { + ctx.Logger().Errorf("failed to get userID: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get userID: %w", err)) + } + r := controller.NewResponse() + res, err = r.GetMyResponses(ctx, params, userID) + if err != nil { + ctx.Logger().Errorf("failed to get my responses: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get my responses: %+w", err)) + } return ctx.JSON(200, res) } diff --git a/model/respondents.go b/model/respondents.go index 56813245..a5f93e42 100644 --- a/model/respondents.go +++ b/model/respondents.go @@ -18,5 +18,6 @@ type IRespondent interface { GetRespondentDetail(ctx context.Context, responseID int) (RespondentDetail, error) GetRespondentDetails(ctx context.Context, questionnaireID int, sort string, onlyMyResponse bool, userID string) ([]RespondentDetail, error) GetRespondentsUserIDs(ctx context.Context, questionnaireIDs []int) ([]Respondents, error) + GetMyResponsesID(ctx context.Context, sort string, userID string) ([]int, error) CheckRespondent(ctx context.Context, userID string, questionnaireID int) (bool, error) } diff --git a/model/respondents_impl.go b/model/respondents_impl.go index bcf55d27..92d29ecb 100755 --- a/model/respondents_impl.go +++ b/model/respondents_impl.go @@ -386,6 +386,25 @@ func (*Respondent) GetRespondentsUserIDs(ctx context.Context, questionnaireIDs [ return respondents, nil } +// GetMyResponses 自分のすべての回答を取得 +func (*Response) GetMyResponsesID(ctx context.Context, userID int) ([]int, error) { + db, err := getTx(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get transaction: %w", err) + } + + responsesID := []int{} + err = db. + Where("user_traqid = ?", userID). + Select("response_id"). + Find(&responsesID).Error + if err != nil { + return nil, fmt.Errorf("failed to get responsesID: %w", err) + } + + return responsesID, nil +} + // CheckRespondent 回答者かどうかの確認 func (*Respondent) CheckRespondent(ctx context.Context, userID string, questionnaireID int) (bool, error) { db, err := getTx(ctx) diff --git a/model/targets.go b/model/targets.go index e6557b12..a1bb5506 100644 --- a/model/targets.go +++ b/model/targets.go @@ -9,4 +9,5 @@ type ITarget interface { InsertTargets(ctx context.Context, questionnaireID int, targets []string) error DeleteTargets(ctx context.Context, questionnaireID int) error GetTargets(ctx context.Context, questionnaireIDs []int) ([]Targets, error) + IsTargetingMe(ctx context.Context, quesionnairID int, userID string) (bool, error) } diff --git a/model/targets_impl.go b/model/targets_impl.go index c3d73dd8..ab9d2b47 100644 --- a/model/targets_impl.go +++ b/model/targets_impl.go @@ -80,3 +80,8 @@ func (*Target) GetTargets(ctx context.Context, questionnaireIDs []int) ([]Target return targets, nil } + +func(*Target) IsTargetingME(ctx context.Context, questionnairID int, userID string) (bool, error) { + // todo: check if the questionnair is targeting me + return true, nil +} \ No newline at end of file From 1b700da24616b5ee9ddaf2c7d173d9b51782bab2 Mon Sep 17 00:00:00 2001 From: Eraxyso <130852025+Eraxyso@users.noreply.github.com> Date: Mon, 12 Aug 2024 09:03:10 +0000 Subject: [PATCH 03/10] feat: implement GetResponse --- controller/response.go | 16 ++++++++++++++++ handler/response.go | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/controller/response.go b/controller/response.go index 8d2df275..bdef5721 100644 --- a/controller/response.go +++ b/controller/response.go @@ -101,3 +101,19 @@ func (r Response) GetMyResponses(ctx echo.Context, params openapi.GetMyResponses return res, nil } + +func (r Response) GetResponse(ctx echo.Context, responseID openapi.ResponseIDInPath) (openapi.Response, error) { + responseDetail, err := r.IRespondent.GetRespondentDetail(ctx.Request().Context(), responseID) + if err != nil { + ctx.Logger().Errorf("failed to get respondent detail: %+v", err) + return openapi.Response{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get respondent detail: %+w", err)) + } + + res, err := respondentDetail2Response(ctx, responseDetail) + if err != nil { + ctx.Logger().Errorf("failed to convert respondent detail into response: %+v", err) + return openapi.Response{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to convert respondent detail into response: %+w", err)) + } + + return res, nil +} diff --git a/handler/response.go b/handler/response.go index 40cbda84..1ecbf785 100644 --- a/handler/response.go +++ b/handler/response.go @@ -36,6 +36,12 @@ func (h Handler) DeleteResponse(ctx echo.Context, responseID openapi.ResponseIDI func (h Handler) GetResponse(ctx echo.Context, responseID openapi.ResponseIDInPath) error { res := openapi.Response{} + r := controller.NewResponse() + res, err := r.GetResponse(ctx, responseID) + if err != nil { + ctx.Logger().Errorf("failed to get my response: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get response: %+w", err)) + } return ctx.JSON(200, res) } From b09232718594ac6a2a4f0fa090dea6c4606b647d Mon Sep 17 00:00:00 2001 From: Eraxyso <130852025+Eraxyso@users.noreply.github.com> Date: Sun, 25 Aug 2024 18:45:10 +0000 Subject: [PATCH 04/10] feat: implement DeleteResponse --- controller/response.go | 32 ++++++++++++++++++++++++++++++++ handler/response.go | 13 +++++++++++++ 2 files changed, 45 insertions(+) diff --git a/controller/response.go b/controller/response.go index bdef5721..7f8f05dc 100644 --- a/controller/response.go +++ b/controller/response.go @@ -1,6 +1,7 @@ package controller import ( + "errors" "fmt" "net/http" "time" @@ -14,6 +15,7 @@ import ( type Response struct { model.IQuestionnaire model.IRespondent + model.IResponse model.ITarget } @@ -117,3 +119,33 @@ func (r Response) GetResponse(ctx echo.Context, responseID openapi.ResponseIDInP return res, nil } + +func (r Response) DeleteResponse(ctx echo.Context, responseID openapi.ResponseIDInPath, userID string) error { + limit, err := r.IQuestionnaire.GetQuestionnaireLimitByResponseID(ctx.Request().Context(), responseID) + if err != nil { + if errors.Is(err, model.ErrRecordNotFound) { + ctx.Logger().Errorf("failed to find response by response ID: %+v", err) + return echo.NewHTTPError(http.StatusNotFound, fmt.Errorf("failed to find response by response ID: %w", err)) + } + ctx.Logger().Errorf("failed to get questionnaire limit by response ID: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire limit by response ID: %w", err)) + } + if limit.Valid && limit.Time.Before(time.Now()) { + ctx.Logger().Errorf("unable delete the expired response") + return echo.NewHTTPError(http.StatusMethodNotAllowed, fmt.Errorf("unable delete the expired response")) + } + + err = r.IRespondent.DeleteRespondent(ctx.Request().Context(), responseID) + if err != nil { + ctx.Logger().Errorf("failed to delete respondent: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to delete respondent: %w", err)) + } + + err = r.IResponse.DeleteResponse(ctx.Request().Context(), responseID) + if err != nil { + ctx.Logger().Errorf("failed to delete response: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to delete response: %w", err)) + } + + return nil +} diff --git a/handler/response.go b/handler/response.go index 1ecbf785..982a29f0 100644 --- a/handler/response.go +++ b/handler/response.go @@ -29,6 +29,19 @@ func (h Handler) GetMyResponses(ctx echo.Context, params openapi.GetMyResponsesP // (DELETE /responses/{responseID}) func (h Handler) DeleteResponse(ctx echo.Context, responseID openapi.ResponseIDInPath) error { + userID, err := getUserID(ctx) + if err != nil { + ctx.Logger().Errorf("failed to get userID: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get userID: %w", err)) + } + + r := controller.NewResponse() + err = r.DeleteResponse(ctx, responseID, userID) + if err != nil { + ctx.Logger().Errorf("failed to delete response: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to delete response: %w", err)) + } + return ctx.NoContent(200) } From 63892f462a2da8479f9596c34e5323c3f1270817 Mon Sep 17 00:00:00 2001 From: Eraxyso <130852025+Eraxyso@users.noreply.github.com> Date: Wed, 28 Aug 2024 09:38:53 +0000 Subject: [PATCH 05/10] feat: implement GetMyResponses(complete) --- model/respondents_test.go | 95 +++++++++++++++++++++++++++++++++++++++ model/targets_impl.go | 21 +++++++-- model/targets_test.go | 66 +++++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 3 deletions(-) diff --git a/model/respondents_test.go b/model/respondents_test.go index cafc7dd7..cb38c8e9 100644 --- a/model/respondents_test.go +++ b/model/respondents_test.go @@ -990,6 +990,101 @@ func TestGetRespondentsUserIDs(t *testing.T) { } } +func TestGetMyResponseIDs(t *testing.T) { + t.Parallel() + + assertion := assert.New(t) + ctx := context.Background() + + questionnaireID, err := questionnaireImpl.InsertQuestionnaire(ctx, "第1回集会らん☆ぷろ募集アンケート", "第1回メンバー集会でのらん☆ぷろで発表したい人を募集します らん☆ぷろで発表したい人あつまれー!", null.NewTime(time.Now(), false), "private") + require.NoError(t, err) + + respondents := []Respondents{ + { + QuestionnaireID: questionnaireID, + UserTraqid: userOne, + SubmittedAt: null.NewTime(time.Now(), true), + }, + { + QuestionnaireID: questionnaireID, + UserTraqid: userTwo, + SubmittedAt: null.NewTime(time.Now(), true), + }, + { + QuestionnaireID: questionnaireID, + UserTraqid: userTwo, + SubmittedAt: null.NewTime(time.Now(), true), + }, + } + responseIDs := []int{} + for _, respondent := range respondents { + responseID, err := respondentImpl.InsertRespondent(ctx, respondent.UserTraqid, questionnaireID, respondent.SubmittedAt) + require.NoError(t, err) + responseIDs = append(responseIDs, responseID) + } + + type args struct { + userID string + } + type expect struct { + isErr bool + err error + responseIDs []int + } + type test struct { + description string + args + expect + } + + testCases := []test{ + { + description: "valid user with one resonse", + args: args{ + userID: userOne, + }, + expect: expect{ + responseIDs: []int{responseIDs[1]}, + }, + }, + { + description: "valid user with multiple responses", + args: args{ + userID: userTwo, + }, + expect: expect{ + responseIDs: []int{responseIDs[2], responseIDs[3]}, + }, + }, + { + description: "valid user with no response", + args: args{ + userID: userThree, + }, + expect: expect{ + responseIDs: []int{}, + }, + }, + } + + for _, testCase := range testCases { + MyResponseIDs, err := respondentImpl.GetMyResponseIDs(ctx, testCase.args.userID) + + if !testCase.expect.isErr { + assertion.NoError(err, testCase.description, "no error") + } else if testCase.expect.err != nil { + assertion.Equal(true, errors.Is(err, testCase.expect.err), testCase.description, "errorIs") + } else { + assertion.Error(err, testCase.description, "any error") + } + if err != nil { + continue + } + + assertion.Equal(testCase.expect.responseIDs, MyResponseIDs, testCase.description, "responseIDs") + } +} + func TestTestCheckRespondent(t *testing.T) { t.Parallel() diff --git a/model/targets_impl.go b/model/targets_impl.go index ab9d2b47..ccad5b1e 100644 --- a/model/targets_impl.go +++ b/model/targets_impl.go @@ -81,7 +81,22 @@ func (*Target) GetTargets(ctx context.Context, questionnaireIDs []int) ([]Target return targets, nil } -func(*Target) IsTargetingME(ctx context.Context, questionnairID int, userID string) (bool, error) { - // todo: check if the questionnair is targeting me - return true, nil +func(*Target) IsTargetingMe(ctx context.Context, questionnairID int, userID string) (bool, error) { + db, err := getTx(ctx) + if err != nil { + return false, fmt.Errorf("failed to get transaction: %w", err) + } + + var count int64 + err = db. + Where("questionnaire_id = ? AND user_traqid = ?", questionnairID, userID). + Count(&count).Error + if err != nil { + return false, fmt.Errorf("failed to get targets which are targeting me: %w", err) + } + + if count > 0 { + return true, nil + } + return false, nil } \ No newline at end of file diff --git a/model/targets_test.go b/model/targets_test.go index a00d7487..24703d1e 100644 --- a/model/targets_test.go +++ b/model/targets_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "gorm.io/gorm" ) @@ -308,3 +309,68 @@ func TestGetTargets(t *testing.T) { }) } } + +func TestIsTargetingMe(t *testing.T) { + t.Parallel() + + assertion := assert.New(t) + ctx := context.Background() + + questionnaireID, err := questionnaireImpl.InsertQuestionnaire(ctx, "第1回集会らん☆ぷろ募集アンケート", "第1回メンバー集会でのらん☆ぷろで発表したい人を募集します らん☆ぷろで発表したい人あつまれー!", null.NewTime(time.Now(), false), "private") + require.NoError(t, err) + + err = targetImpl.InsertTargets(ctx, questionnaireID, []string{userOne}) + require.NoError(t, err) + + type args struct { + userID string + } + type expect struct { + isErr bool + err error + isTargeted bool + } + type test struct { + description string + args + expect + } + + testCases := []test{ + { + description: "is targeted", + args: args{ + userID: userOne, + }, + expect: expect{ + isTargeted: true, + }, + }, + { + description: "not targeted", + args: args{ + userID: userTwo, + }, + expect: expect{ + isTargeted: false, + }, + }, + } + + for _, testCase := range testCases { + isTargeted, err := targetImpl.IsTargetingMe(ctx, questionnaireID, testCase.args.userID) + + if !testCase.expect.isErr { + assertion.NoError(err, testCase.description, "no error") + } else if testCase.expect.err != nil { + assertion.Equal(true, errors.Is(err, testCase.expect.err), testCase.description, "errorIs") + } else { + assertion.Error(err, testCase.description, "any error") + } + if err != nil { + continue + } + + assertion.Equal(testCase.expect.isTargeted, isTargeted, testCase.description, "isTargeted") + } +} From e21b78db65a5a77d852a697562d73b64abb34634 Mon Sep 17 00:00:00 2001 From: Eraxyso <130852025+Eraxyso@users.noreply.github.com> Date: Wed, 28 Aug 2024 10:35:23 +0000 Subject: [PATCH 06/10] fix: fix some errors, optimize some implementations and add existence check for GetResponse --- controller/questionnaire.go | 32 ++++++++++++++++++++++++++++++++ controller/response.go | 20 ++++++++++++-------- handler/questionnaire.go | 28 ++++------------------------ handler/response.go | 6 +++--- model/respondents.go | 2 +- model/respondents_impl.go | 2 +- model/targets_test.go | 2 ++ 7 files changed, 55 insertions(+), 37 deletions(-) diff --git a/controller/questionnaire.go b/controller/questionnaire.go index a0ac8ce9..607ae11d 100644 --- a/controller/questionnaire.go +++ b/controller/questionnaire.go @@ -371,3 +371,35 @@ https://anke-to.trap.jp/responses/new/%d`, questionnaireID, ) } + +func (q Questionnaire) GetQuestionnaireResult(ctx echo.Context, questionnaireID int, userID string) (openapi.Result, error){ + res := openapi.Result{} + + params := openapi.GetQuestionnaireResponsesParams{} + responses, err := q.GetQuestionnaireResponses(ctx, questionnaireID, params, userID) + if err != nil { + ctx.Logger().Errorf("failed to get questionnaire responses: %+v", err) + return openapi.Result{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire responses: %w", err)) + } + + for _, response := range responses { + tmp := struct { + Body []openapi.ResponseBody `json:"body"` + IsDraft bool `json:"is_draft"` + ModifiedAt time.Time `json:"modified_at"` + QuestionnaireId int `json:"questionnaire_id"` + ResponseId int `json:"response_id"` + SubmittedAt time.Time `json:"submitted_at"` + }{ + Body: response.Body, + IsDraft: response.IsDraft, + ModifiedAt: response.ModifiedAt, + QuestionnaireId: response.QuestionnaireId, + ResponseId: response.ResponseId, + SubmittedAt: response.SubmittedAt, + } + res = append(res, tmp) + } + + return res, nil +} diff --git a/controller/response.go b/controller/response.go index 7f8f05dc..a7bd6927 100644 --- a/controller/response.go +++ b/controller/response.go @@ -28,29 +28,29 @@ func (r Response) GetMyResponses(ctx echo.Context, params openapi.GetMyResponses sort := string(*params.Sort) responsesID := []int{} - responsesID, err := r.IRespondent.GetMyResponsesID(ctx.Request().Context(), sort, userID) + responsesID, err := r.IRespondent.GetMyResponseIDs(ctx.Request().Context(), sort, userID) if err != nil { ctx.Logger().Errorf("failed to get my responses ID: %+v", err) - return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire responses: %+w", err)) + return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire responses: %w", err)) } for _, responseID := range responsesID { responseDetail, err := r.IRespondent.GetRespondentDetail(ctx.Request().Context(), responseID) if err != nil { ctx.Logger().Errorf("failed to get respondent detail: %+v", err) - return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get respondent detail: %+w", err)) + return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get respondent detail: %w", err)) } questionnaire, _, _, _, _, _, err := r.IQuestionnaire.GetQuestionnaireInfo(ctx.Request().Context(), responseDetail.QuestionnaireID) if err != nil { ctx.Logger().Errorf("failed to get questionnaire info: %+v", err) - return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire info: %+w", err)) + return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire info: %w", err)) } isTargetingMe, err := r.ITarget.IsTargetingMe(ctx.Request().Context(), responseDetail.QuestionnaireID, userID) if err != nil { ctx.Logger().Errorf("failed to get target info: %+v", err) - return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get target info: %+w", err)) + return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get target info: %w", err)) } questionnaireInfo := struct { @@ -70,7 +70,7 @@ func (r Response) GetMyResponses(ctx echo.Context, params openapi.GetMyResponses response, err := respondentDetail2Response(ctx, responseDetail) if err != nil { ctx.Logger().Errorf("failed to convert respondent detail into response: %+v", err) - return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to convert respondent detail into response: %+w", err)) + return openapi.ResponsesWithQuestionnaireInfo{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to convert respondent detail into response: %w", err)) } tmp := struct { @@ -107,14 +107,18 @@ func (r Response) GetMyResponses(ctx echo.Context, params openapi.GetMyResponses func (r Response) GetResponse(ctx echo.Context, responseID openapi.ResponseIDInPath) (openapi.Response, error) { responseDetail, err := r.IRespondent.GetRespondentDetail(ctx.Request().Context(), responseID) if err != nil { + if errors.Is(err, model.ErrRecordNotFound) { + ctx.Logger().Errorf("failed to find response by response ID: %+v", err) + return openapi.Response{}, echo.NewHTTPError(http.StatusNotFound, fmt.Errorf("failed to find response by response ID: %w", err)) + } ctx.Logger().Errorf("failed to get respondent detail: %+v", err) - return openapi.Response{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get respondent detail: %+w", err)) + return openapi.Response{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get respondent detail: %w", err)) } res, err := respondentDetail2Response(ctx, responseDetail) if err != nil { ctx.Logger().Errorf("failed to convert respondent detail into response: %+v", err) - return openapi.Response{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to convert respondent detail into response: %+w", err)) + return openapi.Response{}, echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to convert respondent detail into response: %w", err)) } return res, nil diff --git a/handler/questionnaire.go b/handler/questionnaire.go index 202f125c..647c67bb 100644 --- a/handler/questionnaire.go +++ b/handler/questionnaire.go @@ -180,31 +180,11 @@ func (h Handler) GetQuestionnaireResult(ctx echo.Context, questionnaireID openap return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get userID: %w", err)) } - params := openapi.GetQuestionnaireResponsesParams{} q := controller.NewQuestionnaire() - responses, err := q.GetQuestionnaireResponses(ctx, questionnaireID, params, userID) - if err != nil { - ctx.Logger().Errorf("failed to get questionnaire responses: %+v", err) - return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire responses: %+w", err)) - } - - for _, response := range responses { - tmp := struct { - Body []openapi.ResponseBody `json:"body"` - IsDraft bool `json:"is_draft"` - ModifiedAt time.Time `json:"modified_at"` - QuestionnaireId int `json:"questionnaire_id"` - ResponseId int `json:"response_id"` - SubmittedAt time.Time `json:"submitted_at"` - }{ - Body: response.Body, - IsDraft: response.IsDraft, - ModifiedAt: response.ModifiedAt, - QuestionnaireId: response.QuestionnaireId, - ResponseId: response.ResponseId, - SubmittedAt: response.SubmittedAt, - } - res = append(res, tmp) + res, err = q.GetQuestionnaireResult(ctx, questionnaireID, userID) + if err != nil { + ctx.Logger().Errorf("failed to get questionnaire result: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get questionnaire result: %w", err)) } return ctx.JSON(200, res) diff --git a/handler/response.go b/handler/response.go index 982a29f0..1f47bcd2 100644 --- a/handler/response.go +++ b/handler/response.go @@ -22,7 +22,7 @@ func (h Handler) GetMyResponses(ctx echo.Context, params openapi.GetMyResponsesP res, err = r.GetMyResponses(ctx, params, userID) if err != nil { ctx.Logger().Errorf("failed to get my responses: %+v", err) - return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get my responses: %+w", err)) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get my responses: %w", err)) } return ctx.JSON(200, res) } @@ -52,8 +52,8 @@ func (h Handler) GetResponse(ctx echo.Context, responseID openapi.ResponseIDInPa r := controller.NewResponse() res, err := r.GetResponse(ctx, responseID) if err != nil { - ctx.Logger().Errorf("failed to get my response: %+v", err) - return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get response: %+w", err)) + ctx.Logger().Errorf("failed to get response: %+v", err) + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("failed to get response: %w", err)) } return ctx.JSON(200, res) } diff --git a/model/respondents.go b/model/respondents.go index a5f93e42..e5cff356 100644 --- a/model/respondents.go +++ b/model/respondents.go @@ -18,6 +18,6 @@ type IRespondent interface { GetRespondentDetail(ctx context.Context, responseID int) (RespondentDetail, error) GetRespondentDetails(ctx context.Context, questionnaireID int, sort string, onlyMyResponse bool, userID string) ([]RespondentDetail, error) GetRespondentsUserIDs(ctx context.Context, questionnaireIDs []int) ([]Respondents, error) - GetMyResponsesID(ctx context.Context, sort string, userID string) ([]int, error) + GetMyResponseIDs(ctx context.Context, sort string, userID string) ([]int, error) CheckRespondent(ctx context.Context, userID string, questionnaireID int) (bool, error) } diff --git a/model/respondents_impl.go b/model/respondents_impl.go index 92d29ecb..3c7a6cb0 100755 --- a/model/respondents_impl.go +++ b/model/respondents_impl.go @@ -387,7 +387,7 @@ func (*Respondent) GetRespondentsUserIDs(ctx context.Context, questionnaireIDs [ } // GetMyResponses 自分のすべての回答を取得 -func (*Response) GetMyResponsesID(ctx context.Context, userID int) ([]int, error) { +func (*Respondent) GetMyResponseIDs(ctx context.Context, userID string) ([]int, error) { db, err := getTx(ctx) if err != nil { return nil, fmt.Errorf("failed to get transaction: %w", err) diff --git a/model/targets_test.go b/model/targets_test.go index 24703d1e..fd73aae2 100644 --- a/model/targets_test.go +++ b/model/targets_test.go @@ -4,9 +4,11 @@ import ( "context" "errors" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gopkg.in/guregu/null.v4" "gorm.io/gorm" ) From bd06106aa7bc5aee6d9b6586858cfbc787d9fe42 Mon Sep 17 00:00:00 2001 From: Eraxyso <130852025+Eraxyso@users.noreply.github.com> Date: Fri, 30 Aug 2024 06:35:55 +0000 Subject: [PATCH 07/10] style: add missing space --- controller/questionnaire.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/questionnaire.go b/controller/questionnaire.go index 607ae11d..b2d74604 100644 --- a/controller/questionnaire.go +++ b/controller/questionnaire.go @@ -372,7 +372,7 @@ https://anke-to.trap.jp/responses/new/%d`, ) } -func (q Questionnaire) GetQuestionnaireResult(ctx echo.Context, questionnaireID int, userID string) (openapi.Result, error){ +func (q Questionnaire) GetQuestionnaireResult(ctx echo.Context, questionnaireID int, userID string) (openapi.Result, error) { res := openapi.Result{} params := openapi.GetQuestionnaireResponsesParams{} From 54e993dfc997fdb08d2f6a486f7024a3f80160c7 Mon Sep 17 00:00:00 2001 From: Eraxyso <130852025+Eraxyso@users.noreply.github.com> Date: Fri, 30 Aug 2024 06:44:00 +0000 Subject: [PATCH 08/10] style: format code --- model/targets_impl.go | 6 +++--- model/targets_test.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/model/targets_impl.go b/model/targets_impl.go index ccad5b1e..41350884 100644 --- a/model/targets_impl.go +++ b/model/targets_impl.go @@ -13,7 +13,7 @@ func NewTarget() *Target { return new(Target) } -//Targets targetsテーブルの構造体 +// Targets targetsテーブルの構造体 type Targets struct { QuestionnaireID int `gorm:"type:int(11) AUTO_INCREMENT;not null;primaryKey"` UserTraqid string `gorm:"type:varchar(32);size:32;not null;primaryKey"` @@ -81,7 +81,7 @@ func (*Target) GetTargets(ctx context.Context, questionnaireIDs []int) ([]Target return targets, nil } -func(*Target) IsTargetingMe(ctx context.Context, questionnairID int, userID string) (bool, error) { +func (*Target) IsTargetingMe(ctx context.Context, questionnairID int, userID string) (bool, error) { db, err := getTx(ctx) if err != nil { return false, fmt.Errorf("failed to get transaction: %w", err) @@ -99,4 +99,4 @@ func(*Target) IsTargetingMe(ctx context.Context, questionnairID int, userID stri return true, nil } return false, nil -} \ No newline at end of file +} diff --git a/model/targets_test.go b/model/targets_test.go index fd73aae2..71404545 100644 --- a/model/targets_test.go +++ b/model/targets_test.go @@ -328,9 +328,9 @@ func TestIsTargetingMe(t *testing.T) { userID string } type expect struct { - isErr bool - err error - isTargeted bool + isErr bool + err error + isTargeted bool } type test struct { description string From 18780111a1c68116f5ba24b19b65df6283a4f09a Mon Sep 17 00:00:00 2001 From: Eraxyso <130852025+Eraxyso@users.noreply.github.com> Date: Fri, 30 Aug 2024 07:00:29 +0000 Subject: [PATCH 09/10] style: remove unused import --- handler/questionnaire.go | 1 - 1 file changed, 1 deletion(-) diff --git a/handler/questionnaire.go b/handler/questionnaire.go index 647c67bb..c8db5526 100644 --- a/handler/questionnaire.go +++ b/handler/questionnaire.go @@ -3,7 +3,6 @@ package handler import ( "fmt" "net/http" - "time" "github.com/labstack/echo/v4" "github.com/traPtitech/anke-to/controller" From 7cba992174582fd7d9fb98c5d94ee15e15bfd8d0 Mon Sep 17 00:00:00 2001 From: Eraxyso <130852025+Eraxyso@users.noreply.github.com> Date: Mon, 2 Sep 2024 18:43:48 +0000 Subject: [PATCH 10/10] fix: specify model of db request in functions respondents/GetMyResponseIDs and targets/IsTargetingMe --- model/respondents_impl.go | 1 + model/targets_impl.go | 1 + 2 files changed, 2 insertions(+) diff --git a/model/respondents_impl.go b/model/respondents_impl.go index 3c7a6cb0..2cbf4aaf 100755 --- a/model/respondents_impl.go +++ b/model/respondents_impl.go @@ -395,6 +395,7 @@ func (*Respondent) GetMyResponseIDs(ctx context.Context, userID string) ([]int, responsesID := []int{} err = db. + Model(&Respondents{}). Where("user_traqid = ?", userID). Select("response_id"). Find(&responsesID).Error diff --git a/model/targets_impl.go b/model/targets_impl.go index 41350884..6e046217 100644 --- a/model/targets_impl.go +++ b/model/targets_impl.go @@ -89,6 +89,7 @@ func (*Target) IsTargetingMe(ctx context.Context, questionnairID int, userID str var count int64 err = db. + Model(&Targets{}). Where("questionnaire_id = ? AND user_traqid = ?", questionnairID, userID). Count(&count).Error if err != nil {