diff --git a/controller/adapter.go b/controller/adapter.go index 43ceed80..714bc283 100644 --- a/controller/adapter.go +++ b/controller/adapter.go @@ -68,7 +68,7 @@ func convertResSharedTo(resSharedTo string) openapi.ResShareType { func createUsersAndGroups(users []string, groups uuid.UUIDs) openapi.UsersAndGroups { res := openapi.UsersAndGroups{ Users: users, - Groups: groups.Strings(), + Groups: groups, } return res } @@ -157,21 +157,14 @@ func convertQuestions(questions []model.Questions) ([]openapi.Question, error) { return res, nil } -// func convertRespondents(respondents []model.Respondents) []string { -// res := []string{} -// for _, respondent := range respondents { -// res = append(res, respondent.UserTraqid) -// } -// return res -// } - -func questionnaire2QuestionnaireDetail(questionnaires model.Questionnaires, adminUsers []string, adminGroups []uuid.UUID, targetUsers []string, targetGroups []uuid.UUID, respondents []string) (openapi.QuestionnaireDetail, error) { +func questionnaire2QuestionnaireDetail(questionnaires model.Questionnaires, admins []string, adminUsers []string, adminGroups []uuid.UUID, targets []string, targetUsers []string, targetGroups []uuid.UUID, respondents []string) (openapi.QuestionnaireDetail, error) { questions, err := convertQuestions(questionnaires.Questions) if err != nil { return openapi.QuestionnaireDetail{}, err } res := openapi.QuestionnaireDetail{ - Admins: createUsersAndGroups(adminUsers, adminGroups), + Admin: createUsersAndGroups(adminUsers, adminGroups), + Admins: admins, CreatedAt: questionnaires.CreatedAt, Description: questionnaires.Description, IsDuplicateAnswerAllowed: questionnaires.IsDuplicateAnswerAllowed, @@ -183,7 +176,8 @@ func questionnaire2QuestionnaireDetail(questionnaires model.Questionnaires, admi Respondents: respondents, ResponseDueDateTime: &questionnaires.ResTimeLimit.Time, ResponseViewableBy: convertResSharedTo(questionnaires.ResSharedTo), - Targets: createUsersAndGroups(targetUsers, targetGroups), + Target: createUsersAndGroups(targetUsers, targetGroups), + Targets: targets, Title: questionnaires.Title, } return res, nil @@ -238,7 +232,7 @@ func respondentDetail2Response(ctx echo.Context, respondentDetail model.Responde case "MultipleChoice": if r.Body.Valid { answer := []int{} - questionnaire, _, _, _, _, _, err := model.NewQuestionnaire().GetQuestionnaireInfo(ctx.Request().Context(), r.QuestionID) + questionnaire, _, _, _, _, _, _, _, err := model.NewQuestionnaire().GetQuestionnaireInfo(ctx.Request().Context(), r.QuestionID) if err != nil { ctx.Logger().Errorf("failed to get questionnaire info: %+v", err) return openapi.Response{}, err @@ -262,7 +256,7 @@ func respondentDetail2Response(ctx echo.Context, respondentDetail model.Responde } case "Checkbox": if r.Body.Valid { - questionnaire, _, _, _, _, _, err := model.NewQuestionnaire().GetQuestionnaireInfo(ctx.Request().Context(), r.QuestionID) + questionnaire, _, _, _, _, _, _, _, err := model.NewQuestionnaire().GetQuestionnaireInfo(ctx.Request().Context(), r.QuestionID) if err != nil { ctx.Logger().Errorf("failed to get questionnaire info: %+v", err) return openapi.Response{}, err diff --git a/controller/middleware.go b/controller/middleware.go index 7f10d008..da69e0db 100644 --- a/controller/middleware.go +++ b/controller/middleware.go @@ -137,7 +137,7 @@ func (m Middleware) QuestionnaireReadAuthenticate(next echo.HandlerFunc) echo.Ha } // 公開されたらOK - questionnaire, _, _, _, _, _, err := m.IQuestionnaire.GetQuestionnaireInfo(c.Request().Context(), questionnaireID) + questionnaire, _, _, _, _, _, _, _, err := m.IQuestionnaire.GetQuestionnaireInfo(c.Request().Context(), questionnaireID) if errors.Is(err, model.ErrRecordNotFound) { c.Logger().Infof("questionnaire not found: %+v", err) return echo.NewHTTPError(http.StatusNotFound, fmt.Errorf("questionnaire not found:%d", questionnaireID)) diff --git a/controller/questionnaire.go b/controller/questionnaire.go index 2bd6df3d..24b278d9 100644 --- a/controller/questionnaire.go +++ b/controller/questionnaire.go @@ -22,38 +22,53 @@ type Questionnaire struct { model.IQuestionnaire model.ITarget model.ITargetGroup + model.ITargetUser model.IAdministrator model.IAdministratorGroup + model.IAdministratorUser model.IQuestion model.IOption model.IScaleLabel model.IValidation model.ITransaction + model.IRespondent traq.IWebhook - Response + *Response } func NewQuestionnaire( questionnaire model.IQuestionnaire, target model.ITarget, + targetGroup model.ITargetGroup, + targetUser model.ITargetUser, administrator model.IAdministrator, + administratorGroup model.IAdministratorGroup, + administratorUser model.IAdministratorUser, question model.IQuestion, option model.IOption, scaleLabel model.IScaleLabel, validation model.IValidation, transaction model.ITransaction, + respodent model.IRespondent, webhook traq.IWebhook, + response *Response, ) *Questionnaire { return &Questionnaire{ - IQuestionnaire: questionnaire, - ITarget: target, - IAdministrator: administrator, - IQuestion: question, - IOption: option, - IScaleLabel: scaleLabel, - IValidation: validation, - ITransaction: transaction, - IWebhook: webhook, + IQuestionnaire: questionnaire, + ITarget: target, + ITargetGroup: targetGroup, + ITargetUser: targetUser, + IAdministrator: administrator, + IAdministratorGroup: administratorGroup, + IAdministratorUser: administratorUser, + IQuestion: question, + IOption: option, + IScaleLabel: scaleLabel, + IValidation: validation, + ITransaction: transaction, + IRespondent: respodent, + IWebhook: webhook, + Response: response, } } @@ -137,12 +152,12 @@ func (q Questionnaire) PostQuestionnaire(c echo.Context, params openapi.PostQues c.Logger().Errorf("failed to insert questionnaire: %+v", err) return err } - allTargetUsers, err := rollOutUsersAndGroups(params.Targets.Users, params.Targets.Groups) + allTargetUsers, err := rollOutUsersAndGroups(params.Target.Users, params.Target.Groups) if err != nil { c.Logger().Errorf("failed to roll out users and groups: %+v", err) return err } - targetGroupNames, err := uuid2GroupNames(params.Targets.Groups) + targetGroupNames, err := uuid2GroupNames(params.Target.Groups) if err != nil { c.Logger().Errorf("failed to get group names: %+v", err) return err @@ -152,17 +167,22 @@ func (q Questionnaire) PostQuestionnaire(c echo.Context, params openapi.PostQues c.Logger().Errorf("failed to insert targets: %+v", err) return err } - err = q.InsertTargetGroups(ctx, questionnaireID, params.Targets.Groups) + err = q.InsertTargetUsers(ctx, questionnaireID, params.Target.Users) if err != nil { c.Logger().Errorf("failed to insert target groups: %+v", err) return err } - allAdminUsers, err := rollOutUsersAndGroups(params.Admins.Users, params.Admins.Groups) + err = q.InsertTargetGroups(ctx, questionnaireID, params.Target.Groups) + if err != nil { + c.Logger().Errorf("failed to insert target groups: %+v", err) + return err + } + allAdminUsers, err := rollOutUsersAndGroups(params.Admin.Users, params.Admin.Groups) if err != nil { c.Logger().Errorf("failed to roll out administrators: %+v", err) return err } - adminGroupNames, err := uuid2GroupNames(params.Admins.Groups) + adminGroupNames, err := uuid2GroupNames(params.Admin.Groups) if err != nil { c.Logger().Errorf("failed to get group names: %+v", err) return err @@ -172,7 +192,12 @@ func (q Questionnaire) PostQuestionnaire(c echo.Context, params openapi.PostQues c.Logger().Errorf("failed to insert administrators: %+v", err) return err } - err = q.InsertAdministratorGroups(ctx, questionnaireID, params.Admins.Groups) + err = q.InsertAdministratorUsers(ctx, questionnaireID, params.Admin.Users) + if err != nil { + c.Logger().Errorf("failed to insert administrator users: %+v", err) + return err + } + err = q.InsertAdministratorGroups(ctx, questionnaireID, params.Admin.Groups) if err != nil { c.Logger().Errorf("failed to insert administrator groups: %+v", err) return err @@ -327,13 +352,13 @@ func (q Questionnaire) PostQuestionnaire(c echo.Context, params openapi.PostQues } } - questionnaireInfo, targets, targetGroups, admins, adminGroups, respondents, err := q.GetQuestionnaireInfo(c.Request().Context(), questionnaireID) + questionnaireInfo, targets, targetUsers, targetGroups, admins, adminUsers, adminGroups, respondents, err := q.GetQuestionnaireInfo(c.Request().Context(), questionnaireID) if err != nil { c.Logger().Errorf("failed to get questionnaire info: %+v", err) return openapi.QuestionnaireDetail{}, echo.NewHTTPError(http.StatusInternalServerError, "failed to get questionnaire info") } - questionnaireDetail, err := questionnaire2QuestionnaireDetail(*questionnaireInfo, admins, adminGroups, targets, targetGroups, respondents) + questionnaireDetail, err := questionnaire2QuestionnaireDetail(*questionnaireInfo, admins, adminUsers, adminGroups, targets, targetUsers, targetGroups, respondents) if err != nil { c.Logger().Errorf("failed to convert questionnaire to questionnaire detail: %+v", err) return openapi.QuestionnaireDetail{}, echo.NewHTTPError(http.StatusInternalServerError, "failed to convert questionnaire to questionnaire detail") @@ -341,11 +366,11 @@ func (q Questionnaire) PostQuestionnaire(c echo.Context, params openapi.PostQues return questionnaireDetail, nil } func (q Questionnaire) GetQuestionnaire(ctx echo.Context, questionnaireID int) (openapi.QuestionnaireDetail, error) { - questionnaireInfo, targets, targetGroups, admins, adminGroups, respondents, err := q.GetQuestionnaireInfo(ctx.Request().Context(), questionnaireID) + questionnaireInfo, targets, targetUsers, targetGroups, admins, adminUsers, adminGroups, respondents, err := q.GetQuestionnaireInfo(ctx.Request().Context(), questionnaireID) if err != nil { return openapi.QuestionnaireDetail{}, err } - questionnaireDetail, err := questionnaire2QuestionnaireDetail(*questionnaireInfo, admins, adminGroups, targets, targetGroups, respondents) + questionnaireDetail, err := questionnaire2QuestionnaireDetail(*questionnaireInfo, admins, adminUsers, adminGroups, targets, targetUsers, targetGroups, respondents) if err != nil { ctx.Logger().Errorf("failed to convert questionnaire to questionnaire detail: %+v", err) return openapi.QuestionnaireDetail{}, echo.NewHTTPError(http.StatusInternalServerError, "failed to convert questionnaire to questionnaire detail") @@ -376,55 +401,69 @@ func (q Questionnaire) EditQuestionnaire(c echo.Context, questionnaireID int, pa c.Logger().Errorf("failed to update questionnaire: %+v", err) return err } - err = q.DeleteTargets(ctx, questionnaireID) - if err != nil { - c.Logger().Errorf("failed to delete targets: %+v", err) - return err - } - err = q.DeleteTargetGroups(ctx, questionnaireID) - if err != nil { - c.Logger().Errorf("failed to delete target groups: %+v", err) - return err - } - allTargetUsers, err := rollOutUsersAndGroups(params.Targets.Users, params.Targets.Groups) - if err != nil { - c.Logger().Errorf("failed to roll out users and groups: %+v", err) - return err - } - err = q.InsertTargets(ctx, questionnaireID, allTargetUsers) - if err != nil { - c.Logger().Errorf("failed to insert targets: %+v", err) - return err - } - err = q.InsertTargetGroups(ctx, questionnaireID, params.Targets.Groups) - if err != nil { - c.Logger().Errorf("failed to insert target groups: %+v", err) - return err - } - err = q.DeleteAdministrators(ctx, questionnaireID) - if err != nil { - c.Logger().Errorf("failed to delete administrators: %+v", err) - return err - } - err = q.DeleteAdministratorGroups(ctx, questionnaireID) - if err != nil { - c.Logger().Errorf("failed to delete administrator groups: %+v", err) - return err - } - allAdminUsers, err := rollOutUsersAndGroups(params.Admins.Users, params.Admins.Groups) - if err != nil { - c.Logger().Errorf("failed to roll out administrators: %+v", err) - return err - } - err = q.InsertAdministrators(ctx, questionnaireID, allAdminUsers) - if err != nil { - c.Logger().Errorf("failed to insert administrators: %+v", err) - return err + if params.Target != nil { + err = q.DeleteTargets(ctx, questionnaireID) + if err != nil { + c.Logger().Errorf("failed to delete targets: %+v", err) + return err + } + err = q.DeleteTargetGroups(ctx, questionnaireID) + if err != nil { + c.Logger().Errorf("failed to delete target groups: %+v", err) + return err + } + allTargetUsers, err := rollOutUsersAndGroups((*params.Target).Users, params.Target.Groups) + if err != nil { + c.Logger().Errorf("failed to roll out users and groups: %+v", err) + return err + } + err = q.InsertTargets(ctx, questionnaireID, allTargetUsers) + if err != nil { + c.Logger().Errorf("failed to insert targets: %+v", err) + return err + } + err = q.InsertTargetUsers(ctx, questionnaireID, params.Target.Users) + if err != nil { + c.Logger().Errorf("failed to insert target users: %+v", err) + return err + } + err = q.InsertTargetGroups(ctx, questionnaireID, params.Target.Groups) + if err != nil { + c.Logger().Errorf("failed to insert target groups: %+v", err) + return err + } } - err = q.InsertAdministratorGroups(ctx, questionnaireID, params.Admins.Groups) - if err != nil { - c.Logger().Errorf("failed to insert administrator groups: %+v", err) - return err + if params.Admin != nil { + err = q.DeleteAdministrators(ctx, questionnaireID) + if err != nil { + c.Logger().Errorf("failed to delete administrators: %+v", err) + return err + } + err = q.DeleteAdministratorGroups(ctx, questionnaireID) + if err != nil { + c.Logger().Errorf("failed to delete administrator groups: %+v", err) + return err + } + allAdminUsers, err := rollOutUsersAndGroups(params.Admin.Users, params.Admin.Groups) + if err != nil { + c.Logger().Errorf("failed to roll out administrators: %+v", err) + return err + } + err = q.InsertAdministrators(ctx, questionnaireID, allAdminUsers) + if err != nil { + c.Logger().Errorf("failed to insert administrators: %+v", err) + return err + } + err = q.InsertAdministratorUsers(ctx, questionnaireID, params.Admin.Users) + if err != nil { + c.Logger().Errorf("failed to insert administrator users: %+v", err) + return err + } + err = q.InsertAdministratorGroups(ctx, questionnaireID, params.Admin.Groups) + if err != nil { + c.Logger().Errorf("failed to insert administrator groups: %+v", err) + return err + } } for questoinNum, question := range params.Questions { b, err := question.MarshalJSON() @@ -648,7 +687,7 @@ func (q Questionnaire) EditQuestionnaireMyRemindStatus(c echo.Context, questionn return nil } - questionnaire, _, _, _, _, _, err := q.GetQuestionnaireInfo(c.Request().Context(), questionnaireID) + questionnaire, _, _, _, _, _, _, _, err := q.GetQuestionnaireInfo(c.Request().Context(), questionnaireID) if err != nil { if errors.Is(err, model.ErrRecordNotFound) { c.Logger().Info("questionnaire not found") diff --git a/controller/reminder.go b/controller/reminder.go index b64dec3b..c58a3c2c 100644 --- a/controller/reminder.go +++ b/controller/reminder.go @@ -101,7 +101,7 @@ func (jq *JobQueue) CheckRemindStatus(questionnaireID int) (bool, error) { func reminderAction(questionnaireID int, leftTimeText string) error { ctx := context.Background() q := model.Questionnaire{} - questionnaire, _, _, administrators, _, respondants, err := q.GetQuestionnaireInfo(ctx, questionnaireID) + questionnaire, _, _, _, administrators, _, _, respondants, err := q.GetQuestionnaireInfo(ctx, questionnaireID) if err != nil { return err } diff --git a/controller/response.go b/controller/response.go index e97eb7ba..0bf71c0a 100644 --- a/controller/response.go +++ b/controller/response.go @@ -59,7 +59,7 @@ func (r Response) GetMyResponses(ctx echo.Context, params openapi.GetMyResponses 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) + 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)) diff --git a/controller/utils.go b/controller/utils.go index 97f484f3..f24419c1 100644 --- a/controller/utils.go +++ b/controller/utils.go @@ -5,7 +5,7 @@ import ( "slices" mapset "github.com/deckarep/golang-set/v2" - // "github.com/google/uuid" + "github.com/google/uuid" "github.com/traPtitech/anke-to/model" "github.com/traPtitech/anke-to/traq" ) @@ -24,32 +24,7 @@ func isAllTargetsReponded(targets []model.Targets, respondents []model.Responden return true } -// func minimizeUsersAndGroups(users []string, groups []uuid.UUID) ([]string, []uuid.UUID, error) { -// ctx := context.Background() -// client := traq.NewTraqAPIClient() -// userSet := mapset.NewSet[string]() -// for _, user := range users { -// userSet.Add(user) -// } -// groupUserSet := mapset.NewSet[string]() -// for _, group := range groups { -// members, err := client.GetGroupMembers(ctx, group.String()) -// if err != nil { -// return nil, nil, err -// } -// for _, member := range members { -// memberTraqID, err := client.GetUserTraqID(ctx, member.Id) -// if err != nil { -// return nil, nil, err -// } -// groupUserSet.Add(memberTraqID) -// } -// } -// userSet = userSet.Difference(groupUserSet) -// return userSet.ToSlice(), groups, nil -// } - -func rollOutUsersAndGroups(users []string, groups []string) ([]string, error) { +func rollOutUsersAndGroups(users []string, groups []uuid.UUID) ([]string, error) { ctx := context.Background() client := traq.NewTraqAPIClient() userSet := mapset.NewSet[string]() @@ -57,7 +32,7 @@ func rollOutUsersAndGroups(users []string, groups []string) ([]string, error) { userSet.Add(user) } for _, group := range groups { - members, err := client.GetGroupMembers(ctx, group) + members, err := client.GetGroupMembers(ctx, group.String()) if err != nil { return nil, err } @@ -72,12 +47,12 @@ func rollOutUsersAndGroups(users []string, groups []string) ([]string, error) { return userSet.ToSlice(), nil } -func uuid2GroupNames(users []string) ([]string, error) { +func uuid2GroupNames(groups []uuid.UUID) ([]string, error) { ctx := context.Background() client := traq.NewTraqAPIClient() groupNames := []string{} - for _, user := range users { - groupName, err := client.GetGroupName(ctx, user) + for _, group := range groups { + groupName, err := client.GetGroupName(ctx, group.String()) if err != nil { return nil, err } diff --git a/docs/db_schema.md b/docs/db_schema.md index 7d1f4523..71656f37 100644 --- a/docs/db_schema.md +++ b/docs/db_schema.md @@ -9,6 +9,24 @@ | questionnaire_id | int(11) | NO | PRI | _NULL_ | | user_traqid | char(32) | NO | PRI | _NULL_ | +### administrator_groups + +アンケートの運営 (編集等ができるグループ)(実際の管理はadministratorsで行い、これは前回選択した内容を提示するためのみに使用される) + +| Field | Type | Null | Key | Default | Extra | 説明など | +| ---------------- | -------- | ---- | --- | ------- | ----- | -------- | +| questionnaire_id | int(11) | NO | PRI | _NULL_ | +| group_id | char(36) | NO | PRI | _NULL_ | + +### administrator_users + +アンケートの運営 (編集等ができるユーザー)(実際の管理はadministratorsで行い、これは前回選択した内容を提示するためのみに使用される) + +| Field | Type | Null | Key | Default | Extra | 説明など | +| ---------------- | -------- | ---- | --- | ------- | ----- | -------- | +| questionnaire_id | int(11) | NO | PRI | _NULL_ | +| user_traqid | char(32) | NO | PRI | _NULL_ | + ### options 選択肢 @@ -110,3 +128,21 @@ | questionnaire_id | int(11) | NO | PRI | _NULL_ | | user_traqid | char(32) | NO | PRI | _NULL_ | | is_canceled | boolean | NO | | false | | アンケートの対象者がキャンセルしたかどうか | + +### target_groups + +選択したアンケートの対象者(グループ)(実際の管理はtargetsで行い、これは前回選択した内容を提示するためのみに使用される) + +| Field | Type | Null | Key | Default | Extra | 説明など | +| ---------------- | -------- | ---- | --- | ------- | ----- | -------- | +| questionnaire_id | int(11) | NO | PRI | _NULL_ | +| group_id | char(36) | NO | PRI | _NULL_ | + +### target_groups + +選択したアンケートの対象者(ユーザー)(実際の管理はtargetsで行い、これは前回選択した内容を提示するためのみに使用される) + +| Field | Type | Null | Key | Default | Extra | 説明など | +| ---------------- | -------- | ---- | --- | ------- | ----- | -------- | +| questionnaire_id | int(11) | NO | PRI | _NULL_ | +| user_traqid | char(32) | NO | PRI | _NULL_ | diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index b14e2474..31666da2 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -91,7 +91,7 @@ paths: # TODO 変数の命名を確認する operationId: editQuestionnaire tags: - questionnaire - description: アンケートの情報を変更します。匿名のアンケートを非匿名アンケートに変更することができません。 + description: アンケートの情報を変更します。匿名のアンケートを非匿名アンケートに変更することができません。admin/targetがnullの場合は管理者/対象者を変更しません。 parameters: - $ref: "#/components/parameters/questionnaireIDInPath" requestBody: @@ -99,7 +99,7 @@ paths: # TODO 変数の命名を確認する content: application/json: schema: - $ref: "#/components/schemas/QuestionnaireDetail" + $ref: "#/components/schemas/EditQuestionnaire" responses: "200": description: 正常にアンケートを変更できました。 @@ -428,10 +428,10 @@ components: - $ref: "#/components/schemas/QuestionnaireIsAnonymous" - $ref: "#/components/schemas/QuestionnaireIsDuplicateAnswerAllowed" - $ref: "#/components/schemas/QuestionnaireIsPublished" - - $ref: "#/components/schemas/QuestionnaireTargetsAndAdmins" NewQuestionnaire: allOf: - $ref: "#/components/schemas/QuestionnaireBase" + - $ref: "#/components/schemas/QuestionnaireTargetsAndAdmins" - properties: questions: type: array @@ -439,21 +439,55 @@ components: $ref: "#/components/schemas/NewQuestion" required: - questions + - targets + - admins + EditQuestionnaire: + allOf: + - $ref: "#/components/schemas/QuestionnaireID" + - $ref: "#/components/schemas/QuestionnaireBase" + - $ref: "#/components/schemas/EditQuestionnaireTargetsAndAdmins" + - properties: + questions: + type: array + items: + $ref: "#/components/schemas/Question" + required: + - questions QuestionnaireDetail: allOf: - $ref: "#/components/schemas/QuestionnaireID" - $ref: "#/components/schemas/QuestionnaireBase" - $ref: "#/components/schemas/QuestionnaireCreatedAt" - $ref: "#/components/schemas/QuestionnaireModifiedAt" - - $ref: "#/components/schemas/Users" + - $ref: "#/components/schemas/QuestionnaireTargetsAndAdmins" - properties: questions: type: array items: $ref: "#/components/schemas/Question" + respondents: + type: array + items: + $ref: "#/components/schemas/TraqId" + description: | + 回答者の一覧。匿名回答の場合はnull。 + targets: + type: array + items: + $ref: "#/components/schemas/TraqId" + description: | + 対象者の一覧。(前回対象者を編集した時点で解析したグループ情報に基づいて作成されたもの) + admins: + type: array + items: + $ref: "#/components/schemas/TraqId" + description: | + 管理者の一覧。(前回対象者を編集した時点で解析したグループ情報に基づいて作成されたもの) required: - questions - respondents + - targets + - admins QuestionnaireSummary: # ResponseCountとRespondentCountを入れてもいいかも allOf: - $ref: "#/components/schemas/QuestionnaireID" @@ -602,13 +636,20 @@ components: QuestionnaireTargetsAndAdmins: type: object properties: - targets: + target: $ref: "#/components/schemas/UsersAndGroups" - admins: + admin: $ref: "#/components/schemas/UsersAndGroups" required: - - targets - - admins + - target + - admin + EditQuestionnaireTargetsAndAdmins: + type: object + properties: + target: + $ref: "#/components/schemas/UsersAndGroups" + admin: + $ref: "#/components/schemas/UsersAndGroups" QuestionnaireIsRemindEnabled: type: object properties: @@ -923,7 +964,7 @@ components: type: array items: type: string - example: "1" + format: uuid description: | Group UUID securitySchemes: diff --git a/model/administratorGroups.go b/model/administratorGroups.go index dfddc73a..5cd09711 100644 --- a/model/administratorGroups.go +++ b/model/administratorGroups.go @@ -1,10 +1,14 @@ package model -import "context" +import ( + "context" + + "github.com/google/uuid" +) // IAdministratorGroup AdministratorGroupのRepository type IAdministratorGroup interface { - InsertAdministratorGroups(ctx context.Context, questionnaireID int, administratorGroups []string) error + InsertAdministratorGroups(ctx context.Context, questionnaireID int, groupID []uuid.UUID) error DeleteAdministratorGroups(ctx context.Context, questionnaireID int) error GetAdministratorGroups(ctx context.Context, questionnaireIDs []int) ([]AdministratorGroups, error) } diff --git a/model/administratorGroups_impl.go b/model/administratorGroups_impl.go index ccf97e6b..7a76e23e 100644 --- a/model/administratorGroups_impl.go +++ b/model/administratorGroups_impl.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/gofrs/uuid" + "github.com/google/uuid" ) // AdministratorGroup AdministratorGroupRepositoryの実装 @@ -20,7 +20,7 @@ type AdministratorGroups struct { GroupID uuid.UUID `gorm:"type:varchar(36);size:36;not null;primaryKey"` } -// InsertAdministratorGroups アンケートの管理者グループを追加 +// InsertAdministratorGroups 選択したアンケート管理者(グループ)を追加 func (*AdministratorGroup) InsertAdministratorGroups(ctx context.Context, questionnaireID int, groupID []uuid.UUID) error { db, err := getTx(ctx) if err != nil { @@ -47,7 +47,7 @@ func (*AdministratorGroup) InsertAdministratorGroups(ctx context.Context, questi return nil } -// DeleteAdministratorGroups アンケートの管理者グループを削除 +// DeleteAdministratorGroups 選択したアンケート管理者(グループ)を削除 func (*AdministratorGroup) DeleteAdministratorGroups(ctx context.Context, questionnaireID int) error { db, err := getTx(ctx) if err != nil { @@ -64,7 +64,7 @@ func (*AdministratorGroup) DeleteAdministratorGroups(ctx context.Context, questi return nil } -// GetAdministratorGroups アンケートの管理者グループを取得 +// GetAdministratorGroups 選択したアンケート管理者(グループ)を取得 func (*AdministratorGroup) GetAdministratorGroups(ctx context.Context, questionnaireIDs []int) ([]AdministratorGroups, error) { db, err := getTx(ctx) if err != nil { diff --git a/model/administratorGroups_test.go b/model/administratorGroups_test.go new file mode 100644 index 00000000..e69de29b diff --git a/model/administratorUsers.go b/model/administratorUsers.go new file mode 100644 index 00000000..ca6725d6 --- /dev/null +++ b/model/administratorUsers.go @@ -0,0 +1,10 @@ +package model + +import "context" + +// IAdministratorUser AdministratorUserのRepository +type IAdministratorUser interface { + InsertAdministratorUsers(ctx context.Context, questionnaireID int, traqID []string) error + DeleteAdministratorUsers(ctx context.Context, questionnaireID int) error + GetAdministratorUsers(ctx context.Context, questionnaireIDs []int) ([]AdministratorUsers, error) +} diff --git a/model/administratorUsers_impl.go b/model/administratorUsers_impl.go new file mode 100644 index 00000000..ad3a8a83 --- /dev/null +++ b/model/administratorUsers_impl.go @@ -0,0 +1,81 @@ +package model + +import ( + "context" + "fmt" +) + +// AdministratorUser AdministratorUserRepositoryの実装 +type AdministratorUser struct{} + +// NewAdministratorUser AdministratorUserRepositoryのコンストラクタ +func NewAdministratorUser() *AdministratorUser { + return new(AdministratorUser) +} + +type AdministratorUsers struct { + QuestionnaireID int `gorm:"type:int(11);not null;primaryKey"` + UserTraqid string `gorm:"type:varchar(32);size:32;not null;primaryKey"` +} + +// InsertAdministratorUsers 選択したアンケート管理者(ユーザー)を追加 +func (*AdministratorUser) InsertAdministratorUsers(ctx context.Context, questionnaireID int, UserTraqid []string) error { + db, err := getTx(ctx) + if err != nil { + return fmt.Errorf("failed to get transaction: %w", err) + } + + if len(UserTraqid) == 0 { + return nil + } + + dbAdministratorUsers := make([]AdministratorUsers, 0, len(UserTraqid)) + for _, administratorUser := range UserTraqid { + dbAdministratorUsers = append(dbAdministratorUsers, AdministratorUsers{ + QuestionnaireID: questionnaireID, + UserTraqid: administratorUser, + }) + } + + err = db.Create(&dbAdministratorUsers).Error + if err != nil { + return fmt.Errorf("failed to insert administrator users: %w", err) + } + + return nil +} + +// DeleteAdministratorUsers 選択したアンケート管理者(ユーザー)を削除 +func (*AdministratorUser) DeleteAdministratorUsers(ctx context.Context, questionnaireID int) error { + db, err := getTx(ctx) + if err != nil { + return fmt.Errorf("failed to get transaction: %w", err) + } + + err = db. + Where("questionnaire_id = ?", questionnaireID). + Delete(AdministratorUsers{}).Error + if err != nil { + return fmt.Errorf("failed to delete administrator users: %w", err) + } + + return nil +} + +// GetAdministratorUsers 選択したアンケート管理者(ユーザー)を取得 +func (*AdministratorUser) GetAdministratorUsers(ctx context.Context, questionnaireIDs []int) ([]AdministratorUsers, error) { + db, err := getTx(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get transaction: %w", err) + } + + var administratorUsers []AdministratorUsers + err = db. + Where("questionnaire_id IN ?", questionnaireIDs). + Find(&administratorUsers).Error + if err != nil { + return nil, fmt.Errorf("failed to get administrator users: %w", err) + } + + return administratorUsers, nil +} diff --git a/model/administratorUsers_test.go b/model/administratorUsers_test.go new file mode 100644 index 00000000..e69de29b diff --git a/model/current.go b/model/current.go index 973a7fda..7efb58ee 100644 --- a/model/current.go +++ b/model/current.go @@ -18,9 +18,13 @@ func AllTables() []interface{} { &Respondents{}, &Responses{}, &Administrators{}, + &AdministratorUsers{}, + &AdministratorGroups{}, &Options{}, &ScaleLabels{}, &Targets{}, + &TargetUsers{}, + &TargetGroups{}, &Validations{}, } } diff --git a/model/questionnaires.go b/model/questionnaires.go index 0826afa6..2a8a9984 100644 --- a/model/questionnaires.go +++ b/model/questionnaires.go @@ -16,7 +16,7 @@ type IQuestionnaire interface { DeleteQuestionnaire(ctx context.Context, questionnaireID int) error GetQuestionnaires(ctx context.Context, userID string, sort string, search string, pageNum int, onlyTargetingMe bool, onlyAdministratedByMe bool) ([]QuestionnaireInfo, int, error) GetAdminQuestionnaires(ctx context.Context, userID string) ([]Questionnaires, error) - GetQuestionnaireInfo(ctx context.Context, questionnaireID int) (*Questionnaires, []string, []uuid.UUID, []string, []uuid.UUID, []string, error) + GetQuestionnaireInfo(ctx context.Context, questionnaireID int) (*Questionnaires, []string, []string, []uuid.UUID, []string, []string, []uuid.UUID, []string, error) GetTargettedQuestionnaires(ctx context.Context, userID string, answered string, sort string) ([]TargettedQuestionnaire, error) GetQuestionnaireLimit(ctx context.Context, questionnaireID int) (null.Time, error) GetQuestionnaireLimitByResponseID(ctx context.Context, responseID int) (null.Time, error) diff --git a/model/questionnaires_impl.go b/model/questionnaires_impl.go index 97937f6e..8cff61af 100755 --- a/model/questionnaires_impl.go +++ b/model/questionnaires_impl.go @@ -22,22 +22,25 @@ func NewQuestionnaire() *Questionnaire { // Questionnaires questionnairesテーブルの構造体 type Questionnaires struct { - ID int `json:"questionnaireID" gorm:"type:int(11) AUTO_INCREMENT;not null;primaryKey"` - Title string `json:"title" gorm:"type:char(50);size:50;not null"` - Description string `json:"description" gorm:"type:text;not null"` - ResTimeLimit null.Time `json:"res_time_limit,omitempty" gorm:"type:TIMESTAMP NULL;default:NULL;"` - DeletedAt gorm.DeletedAt `json:"-" gorm:"type:TIMESTAMP NULL;default:NULL;"` - ResSharedTo string `json:"res_shared_to" gorm:"type:char(30);size:30;not null;default:administrators"` - CreatedAt time.Time `json:"created_at" gorm:"type:timestamp;not null;default:CURRENT_TIMESTAMP"` - ModifiedAt time.Time `json:"modified_at" gorm:"type:timestamp;not null;default:CURRENT_TIMESTAMP"` - Administrators []Administrators `json:"-" gorm:"foreignKey:QuestionnaireID"` - Targets []Targets `json:"-" gorm:"foreignKey:QuestionnaireID"` - TargetGroups []TargetGroups `json:"-" gorm:"foreignKey:QuestionnaireID"` - Questions []Questions `json:"-" gorm:"foreignKey:QuestionnaireID"` - Respondents []Respondents `json:"-" gorm:"foreignKey:QuestionnaireID"` - IsPublished bool `json:"is_published" gorm:"type:boolean;default:false"` - IsAnonymous bool `json:"is_anonymous" gorm:"type:boolean;not null;default:false"` - IsDuplicateAnswerAllowed bool `json:"is_duplicate_answer_allowed" gorm:"type:tinyint(4);size:4;not null;default:0"` + ID int `json:"questionnaireID" gorm:"type:int(11) AUTO_INCREMENT;not null;primaryKey"` + Title string `json:"title" gorm:"type:char(50);size:50;not null"` + Description string `json:"description" gorm:"type:text;not null"` + ResTimeLimit null.Time `json:"res_time_limit,omitempty" gorm:"type:TIMESTAMP NULL;default:NULL;"` + DeletedAt gorm.DeletedAt `json:"-" gorm:"type:TIMESTAMP NULL;default:NULL;"` + ResSharedTo string `json:"res_shared_to" gorm:"type:char(30);size:30;not null;default:administrators"` + CreatedAt time.Time `json:"created_at" gorm:"type:timestamp;not null;default:CURRENT_TIMESTAMP"` + ModifiedAt time.Time `json:"modified_at" gorm:"type:timestamp;not null;default:CURRENT_TIMESTAMP"` + Administrators []Administrators `json:"-" gorm:"foreignKey:QuestionnaireID"` + AdministratorUsers []AdministratorUsers `json:"-" gorm:"foreignKey:QuestionnaireID"` + AdministratorGroups []AdministratorGroups `json:"-" gorm:"foreignKey:QuestionnaireID"` + Targets []Targets `json:"-" gorm:"foreignKey:QuestionnaireID"` + TargetUsers []TargetUsers `json:"-" gorm:"foreignKey:QuestionnaireID"` + TargetGroups []TargetGroups `json:"-" gorm:"foreignKey:QuestionnaireID"` + Questions []Questions `json:"-" gorm:"foreignKey:QuestionnaireID"` + Respondents []Respondents `json:"-" gorm:"foreignKey:QuestionnaireID"` + IsPublished bool `json:"is_published" gorm:"type:boolean;default:false"` + IsAnonymous bool `json:"is_anonymous" gorm:"type:boolean;not null;default:false"` + IsDuplicateAnswerAllowed bool `json:"is_duplicate_answer_allowed" gorm:"type:tinyint(4);size:4;not null;default:0"` } // BeforeCreate Update時に自動でmodified_atを現在時刻に @@ -291,16 +294,18 @@ func (*Questionnaire) GetAdminQuestionnaires(ctx context.Context, userID string) } // GetQuestionnaireInfo アンケートの詳細な情報取得 -func (*Questionnaire) GetQuestionnaireInfo(ctx context.Context, questionnaireID int) (*Questionnaires, []string, []uuid.UUID, []string, []uuid.UUID, []string, error) { +func (*Questionnaire) GetQuestionnaireInfo(ctx context.Context, questionnaireID int) (*Questionnaires, []string, []string, []uuid.UUID, []string, []string, []uuid.UUID, []string, error) { db, err := getTx(ctx) if err != nil { - return nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get tx: %w", err) + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get tx: %w", err) } questionnaire := Questionnaires{} targets := []string{} + targetUsers := []string{} targetGroups := []uuid.UUID{} administrators := []string{} + administratorUsers := []string{} administoratorGroups := []uuid.UUID{} respondents := []string{} @@ -309,10 +314,10 @@ func (*Questionnaire) GetQuestionnaireInfo(ctx context.Context, questionnaireID Preload("Targets"). First(&questionnaire).Error if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, nil, nil, nil, nil, nil, ErrRecordNotFound + return nil, nil, nil, nil, nil, nil, nil, nil, ErrRecordNotFound } if err != nil { - return nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get a questionnaire: %w", err) + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get a questionnaire: %w", err) } err = db. @@ -321,7 +326,25 @@ func (*Questionnaire) GetQuestionnaireInfo(ctx context.Context, questionnaireID Where("questionnaire_id = ?", questionnaire.ID). Pluck("user_traqid", &targets).Error if err != nil { - return nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get targets: %w", err) + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get targets: %w", err) + } + + err = db. + Session(&gorm.Session{NewDB: true}). + Table("target_users"). + Where("questionnaire_id = ?", questionnaire.ID). + Pluck("user_traqid", &targetUsers).Error + if err != nil { + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get target users: %w", err) + } + + err = db. + Session(&gorm.Session{NewDB: true}). + Table("target_groups"). + Where("questionnaire_id = ?", questionnaire.ID). + Pluck("group_id", &targetGroups).Error + if err != nil { + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get target groups: %w", err) } err = db. @@ -330,7 +353,25 @@ func (*Questionnaire) GetQuestionnaireInfo(ctx context.Context, questionnaireID Where("questionnaire_id = ?", questionnaire.ID). Pluck("user_traqid", &administrators).Error if err != nil { - return nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get administrators: %w", err) + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get administrators: %w", err) + } + + err = db. + Session(&gorm.Session{NewDB: true}). + Table("administrator_users"). + Where("questionnaire_id = ?", questionnaire.ID). + Pluck("user_traqid", &administratorUsers).Error + if err != nil { + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get administrator users: %w", err) + } + + err = db. + Session(&gorm.Session{NewDB: true}). + Table("administrator_groups"). + Where("questionnaire_id = ?", questionnaire.ID). + Pluck("group_id", &administoratorGroups).Error + if err != nil { + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get administrator groups: %w", err) } err = db. @@ -339,10 +380,10 @@ func (*Questionnaire) GetQuestionnaireInfo(ctx context.Context, questionnaireID Where("questionnaire_id = ? AND deleted_at IS NULL AND submitted_at IS NOT NULL", questionnaire.ID). Pluck("user_traqid", &respondents).Error if err != nil { - return nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get respondents: %w", err) + return nil, nil, nil, nil, nil, nil, nil, nil, fmt.Errorf("failed to get respondents: %w", err) } - return &questionnaire, targets, targetGroups, administrators, administoratorGroups, respondents, nil + return &questionnaire, targets, targetUsers, targetGroups, administrators, administratorUsers, administoratorGroups, respondents, nil } // GetTargettedQuestionnaires targetになっているアンケートの取得 diff --git a/model/questionnaires_test.go b/model/questionnaires_test.go index dcf3a520..de3ac90e 100644 --- a/model/questionnaires_test.go +++ b/model/questionnaires_test.go @@ -1540,7 +1540,7 @@ func getQuestionnaireInfoTest(t *testing.T) { for _, testCase := range testCases { ctx := context.Background() - actualQuestionnaire, actualTargets, _, actualAdministrators, _, actualRespondents, err := questionnaireImpl.GetQuestionnaireInfo(ctx, testCase.questionnaireID) + actualQuestionnaire, actualTargets, _, _, actualAdministrators, _, _, actualRespondents, err := questionnaireImpl.GetQuestionnaireInfo(ctx, testCase.questionnaireID) // TODO with https://github.com/traPtitech/anke-to/issues/1289 if !testCase.expect.isErr { diff --git a/model/targetGroups.go b/model/targetGroups.go index 7217c148..d5085b59 100644 --- a/model/targetGroups.go +++ b/model/targetGroups.go @@ -2,11 +2,13 @@ package model import ( "context" + + "github.com/google/uuid" ) // ITargetGroup TargetGroupのRepository type ITargetGroup interface { - InsertTargetGroups(ctx context.Context, questionnaireID int, groupID []string) error + InsertTargetGroups(ctx context.Context, questionnaireID int, groupID []uuid.UUID) error GetTargetGroups(ctx context.Context, questionnaireIDs []int) ([]TargetGroups, error) DeleteTargetGroups(ctx context.Context, questionnaireIDs int) error } diff --git a/model/targetGroups_impl.go b/model/targetGroups_impl.go index ea04f23d..28378dd6 100644 --- a/model/targetGroups_impl.go +++ b/model/targetGroups_impl.go @@ -4,15 +4,15 @@ import ( "context" "fmt" - "github.com/gofrs/uuid" + "github.com/google/uuid" ) // TargetGroup TargetGroupsRepositoryの実装 type TargetGroup struct{} // NewTargetGroups TargetGroupsのコンストラクター -func NewTargetGroups() *TargetGroups { - return new(TargetGroups) +func NewTargetGroup() *TargetGroup { + return new(TargetGroup) } // TargetGroups targets_groupsテーブルの構造体 @@ -21,7 +21,7 @@ type TargetGroups struct { GroupID uuid.UUID `gorm:"type:char(36);size:36;not null;primaryKey"` } -// InsertTargetGroups アンケートの対象としてuser_groupを追加 +// InsertTargetGroups 選択したアンケート対象者(グループ)を追加 func (*TargetGroup) InsertTargetGroups(ctx context.Context, questionnaireID int, groupID []uuid.UUID) error { db, err := getTx(ctx) if err != nil { @@ -48,7 +48,7 @@ func (*TargetGroup) InsertTargetGroups(ctx context.Context, questionnaireID int, return nil } -// GetTargetGroups アンケートの対象としてuser_groupを取得 +// GetTargetGroups 選択したアンケート対象者(グループ)を取得 func (*TargetGroup) GetTargetGroups(ctx context.Context, questionnaireIDs []int) ([]TargetGroups, error) { db, err := getTx(ctx) if err != nil { @@ -66,7 +66,7 @@ func (*TargetGroup) GetTargetGroups(ctx context.Context, questionnaireIDs []int) return targetGroups, nil } -// DeleteTargetGroups アンケートの対象としてuser_groupを削除 +// DeleteTargetGroups 選択したアンケート対象者(グループ)を削除 func (*TargetGroup) DeleteTargetGroups(ctx context.Context, questionnaireID int) error { db, err := getTx(ctx) if err != nil { diff --git a/model/targetGroups_test.go b/model/targetGroups_test.go new file mode 100644 index 00000000..e69de29b diff --git a/model/targetUsers.go b/model/targetUsers.go new file mode 100644 index 00000000..0bf69a02 --- /dev/null +++ b/model/targetUsers.go @@ -0,0 +1,12 @@ +package model + +import ( + "context" +) + +// ITargetUser TargetUserのRepository +type ITargetUser interface { + InsertTargetUsers(ctx context.Context, questionnaireID int, traqID []string) error + GetTargetUsers(ctx context.Context, questionnaireIDs []int) ([]TargetUsers, error) + DeleteTargetUsers(ctx context.Context, questionnaireIDs int) error +} diff --git a/model/targetUsers_impl.go b/model/targetUsers_impl.go new file mode 100644 index 00000000..121c853a --- /dev/null +++ b/model/targetUsers_impl.go @@ -0,0 +1,82 @@ +package model + +import ( + "context" + "fmt" +) + +// TargetUser TargetUsersRepositoryの実装 +type TargetUser struct{} + +// NewTargetUsers TargetUsersのコンストラクター +func NewTargetUser() *TargetUser { + return new(TargetUser) +} + +// TargetUsers targets_usersテーブルの構造体 +type TargetUsers struct { + QuestionnaireID int `gorm:"type:int(11) AUTO_INCREMENT;not null;primaryKey"` + UserTraqid string `gorm:"type:varchar(32);size:32;not null;primaryKey"` +} + +// InsertTargetUsers 選択したアンケート対象者(ユーザー)を追加 +func (*TargetUser) InsertTargetUsers(ctx context.Context, questionnaireID int, traqID []string) error { + db, err := getTx(ctx) + if err != nil { + return fmt.Errorf("failed to get transaction: %w", err) + } + + if len(traqID) == 0 { + return nil + } + + dbTargetUsers := make([]TargetUsers, 0, len(traqID)) + for _, targetUser := range traqID { + dbTargetUsers = append(dbTargetUsers, TargetUsers{ + QuestionnaireID: questionnaireID, + UserTraqid: targetUser, + }) + } + + err = db.Create(&dbTargetUsers).Error + if err != nil { + return fmt.Errorf("failed to insert target users: %w", err) + } + + return nil +} + +// GetTargetUsers 選択したアンケート対象者(ユーザー)を取得 +func (*TargetUser) GetTargetUsers(ctx context.Context, questionnaireIDs []int) ([]TargetUsers, error) { + db, err := getTx(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get transaction: %w", err) + } + + var TargetUsers []TargetUsers + err = db. + Where("questionnaire_id IN ?", questionnaireIDs). + Find(&TargetUsers).Error + if err != nil { + return nil, fmt.Errorf("failed to get target users: %w", err) + } + + return TargetUsers, nil +} + +// DeleteTargetUsers 選択したアンケート対象者(ユーザー)を削除 +func (*TargetUser) DeleteTargetUsers(ctx context.Context, questionnaireID int) error { + db, err := getTx(ctx) + if err != nil { + return fmt.Errorf("failed to get transaction: %w", err) + } + + err = db. + Where("questionnaire_id = ?", questionnaireID). + Delete(&TargetUsers{}).Error + if err != nil { + return fmt.Errorf("failed to delete target users: %w", err) + } + + return nil +} diff --git a/model/targetUsers_test.go b/model/targetUsers_test.go new file mode 100644 index 00000000..e69de29b diff --git a/model/v3.go b/model/v3.go index b28160e9..9130e28e 100644 --- a/model/v3.go +++ b/model/v3.go @@ -4,6 +4,7 @@ import ( "time" "github.com/go-gormigrate/gormigrate/v2" + "github.com/google/uuid" "gopkg.in/guregu/null.v4" "gorm.io/gorm" ) @@ -18,6 +19,18 @@ func v3() *gormigrate.Migration { if err := tx.AutoMigrate(&v3Questionnaires{}); err != nil { return err } + if err := tx.AutoMigrate(&v3TargetUsers{}); err != nil { + return err + } + if err := tx.AutoMigrate(&v3TargetGroups{}); err != nil { + return err + } + if err := tx.AutoMigrate(&v3AdministratorUsers{}); err != nil { + return err + } + if err := tx.AutoMigrate(&v3AdministratorGroups{}); err != nil { + return err + } return nil }, } @@ -55,3 +68,39 @@ type v3Questionnaires struct { func (*v3Questionnaires) TableName() string { return "questionnaires" } + +type v3TargetUsers struct { + QuestionnaireID int `gorm:"type:int(11) AUTO_INCREMENT;not null;primaryKey"` + UserTraqid string `gorm:"type:varchar(32);size:32;not null;primaryKey"` +} + +func (*v3TargetUsers) TableName() string { + return "targets_users" +} + +type v3TargetGroups struct { + QuestionnaireID int `gorm:"type:int(11) AUTO_INCREMENT;not null;primaryKey"` + GroupID uuid.UUID `gorm:"type:char(36);size:36;not null;primaryKey"` +} + +func (*v3TargetGroups) TableName() string { + return "targets_groups" +} + +type v3AdministratorUsers struct { + QuestionnaireID int `gorm:"type:int(11) AUTO_INCREMENT;not null;primaryKey"` + UserTraqid string `gorm:"type:varchar(32);size:32;not null;primaryKey"` +} + +func (*v3AdministratorUsers) TableName() string { + return "administrator_users" +} + +type v3AdministratorGroups struct { + QuestionnaireID int `gorm:"type:int(11) AUTO_INCREMENT;not null;primaryKey"` + GroupID uuid.UUID `gorm:"type:char(36);size:36;not null;primaryKey"` +} + +func (*v3AdministratorGroups) TableName() string { + return "administrator_groups" +} diff --git a/openapi/spec.go b/openapi/spec.go index 5cfaccae..f75ab73e 100644 --- a/openapi/spec.go +++ b/openapi/spec.go @@ -18,75 +18,78 @@ import ( // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/openapi/types.go b/openapi/types.go index 49d72551..6dee5c18 100644 --- a/openapi/types.go +++ b/openapi/types.go @@ -9,6 +9,7 @@ import ( "time" "github.com/oapi-codegen/runtime" + openapi_types "github.com/oapi-codegen/runtime/types" ) const ( @@ -132,8 +133,39 @@ const ( SortTypeTitleDESC SortType = "-title" ) +// EditQuestionnaire defines model for EditQuestionnaire. +type EditQuestionnaire struct { + Admin *UsersAndGroups `json:"admin,omitempty"` + Description string `json:"description"` + + // IsAnonymous 匿名回答かどうか + IsAnonymous bool `json:"is_anonymous"` + + // IsDuplicateAnswerAllowed 一人が複数回回答できるかどうか + IsDuplicateAnswerAllowed bool `json:"is_duplicate_answer_allowed"` + + // IsPublished アンケートが公開されているかどうか + IsPublished bool `json:"is_published"` + QuestionnaireId int `json:"questionnaire_id"` + Questions []Question `json:"questions"` + + // ResponseDueDateTime 回答期限。この日時を過ぎたら回答できなくなる。nullの場合は回答期限なし。 + ResponseDueDateTime *time.Time `json:"response_due_date_time,omitempty"` + + // ResponseViewableBy アンケートの結果を, 運営は見られる ("admins"), 回答済みの人は見られる ("respondents") 誰でも見られる ("anyone") + ResponseViewableBy ResShareType `json:"response_viewable_by"` + Target *UsersAndGroups `json:"target,omitempty"` + Title string `json:"title"` +} + +// EditQuestionnaireTargetsAndAdmins defines model for EditQuestionnaireTargetsAndAdmins. +type EditQuestionnaireTargetsAndAdmins struct { + Admin *UsersAndGroups `json:"admin,omitempty"` + Target *UsersAndGroups `json:"target,omitempty"` +} + // Groups defines model for Groups. -type Groups = []string +type Groups = []openapi_types.UUID // NewQuestion defines model for NewQuestion. type NewQuestion struct { @@ -146,7 +178,7 @@ type NewQuestion struct { // NewQuestionnaire defines model for NewQuestionnaire. type NewQuestionnaire struct { - Admins UsersAndGroups `json:"admins"` + Admin UsersAndGroups `json:"admin"` Description string `json:"description"` // IsAnonymous 匿名回答かどうか @@ -164,7 +196,7 @@ type NewQuestionnaire struct { // ResponseViewableBy アンケートの結果を, 運営は見られる ("admins"), 回答済みの人は見られる ("respondents") 誰でも見られる ("anyone") ResponseViewableBy ResShareType `json:"response_viewable_by"` - Targets UsersAndGroups `json:"targets"` + Target UsersAndGroups `json:"target"` Title string `json:"title"` } @@ -309,8 +341,7 @@ type QuestionTypeTextLongQuestionType string // QuestionnaireBase defines model for QuestionnaireBase. type QuestionnaireBase struct { - Admins UsersAndGroups `json:"admins"` - Description string `json:"description"` + Description string `json:"description"` // IsAnonymous 匿名回答かどうか IsAnonymous bool `json:"is_anonymous"` @@ -325,9 +356,8 @@ type QuestionnaireBase struct { ResponseDueDateTime *time.Time `json:"response_due_date_time,omitempty"` // ResponseViewableBy アンケートの結果を, 運営は見られる ("admins"), 回答済みの人は見られる ("respondents") 誰でも見られる ("anyone") - ResponseViewableBy ResShareType `json:"response_viewable_by"` - Targets UsersAndGroups `json:"targets"` - Title string `json:"title"` + ResponseViewableBy ResShareType `json:"response_viewable_by"` + Title string `json:"title"` } // QuestionnaireCreatedAt defines model for QuestionnaireCreatedAt. @@ -342,9 +372,12 @@ type QuestionnaireDescription struct { // QuestionnaireDetail defines model for QuestionnaireDetail. type QuestionnaireDetail struct { - Admins UsersAndGroups `json:"admins"` - CreatedAt time.Time `json:"created_at"` - Description string `json:"description"` + Admin UsersAndGroups `json:"admin"` + + // Admins 管理者の一覧。(前回対象者を編集した時点で解析したグループ情報に基づいて作成されたもの) + Admins []TraqId `json:"admins"` + CreatedAt time.Time `json:"created_at"` + Description string `json:"description"` // IsAnonymous 匿名回答かどうか IsAnonymous bool `json:"is_anonymous"` @@ -357,15 +390,20 @@ type QuestionnaireDetail struct { ModifiedAt time.Time `json:"modified_at"` QuestionnaireId int `json:"questionnaire_id"` Questions []Question `json:"questions"` - Respondents Users `json:"respondents"` + + // Respondents 回答者の一覧。匿名回答の場合はnull。 + Respondents []TraqId `json:"respondents"` // ResponseDueDateTime 回答期限。この日時を過ぎたら回答できなくなる。nullの場合は回答期限なし。 ResponseDueDateTime *time.Time `json:"response_due_date_time,omitempty"` // ResponseViewableBy アンケートの結果を, 運営は見られる ("admins"), 回答済みの人は見られる ("respondents") 誰でも見られる ("anyone") ResponseViewableBy ResShareType `json:"response_viewable_by"` - Targets UsersAndGroups `json:"targets"` - Title string `json:"title"` + Target UsersAndGroups `json:"target"` + + // Targets 対象者の一覧。(前回対象者を編集した時点で解析したグループ情報に基づいて作成されたもの) + Targets []TraqId `json:"targets"` + Title string `json:"title"` } // QuestionnaireID defines model for QuestionnaireID. @@ -478,8 +516,8 @@ type QuestionnaireSummary struct { // QuestionnaireTargetsAndAdmins defines model for QuestionnaireTargetsAndAdmins. type QuestionnaireTargetsAndAdmins struct { - Admins UsersAndGroups `json:"admins"` - Targets UsersAndGroups `json:"targets"` + Admin UsersAndGroups `json:"admin"` + Target UsersAndGroups `json:"target"` } // QuestionnaireTitle defines model for QuestionnaireTitle. @@ -608,13 +646,15 @@ type SortType string // TraqId traQ ID type TraqId = string -// Users defines model for Users. +// Users 回答者の一覧。匿名回答の場合はnull。 type Users = []TraqId // UsersAndGroups defines model for UsersAndGroups. type UsersAndGroups struct { Groups Groups `json:"groups"` - Users Users `json:"users"` + + // Users 回答者の一覧。匿名回答の場合はnull。 + Users Users `json:"users"` } // OnlyAdministratedByMeInQuery defines model for onlyAdministratedByMeInQuery. @@ -681,7 +721,7 @@ type GetMyResponsesParams struct { type PostQuestionnaireJSONRequestBody = NewQuestionnaire // EditQuestionnaireJSONRequestBody defines body for EditQuestionnaire for application/json ContentType. -type EditQuestionnaireJSONRequestBody = QuestionnaireDetail +type EditQuestionnaireJSONRequestBody = EditQuestionnaire // EditQuestionnaireMyRemindStatusJSONRequestBody defines body for EditQuestionnaireMyRemindStatus for application/json ContentType. type EditQuestionnaireMyRemindStatusJSONRequestBody = QuestionnaireIsRemindEnabled diff --git a/wire.go b/wire.go index 6ffd397b..8509738b 100644 --- a/wire.go +++ b/wire.go @@ -12,18 +12,21 @@ import ( ) var ( - administratorBind = wire.Bind(new(model.IAdministrator), new(*model.Administrator)) - optionBind = wire.Bind(new(model.IOption), new(*model.Option)) - questionnaireBind = wire.Bind(new(model.IQuestionnaire), new(*model.Questionnaire)) - questionBind = wire.Bind(new(model.IQuestion), new(*model.Question)) - respondentBind = wire.Bind(new(model.IRespondent), new(*model.Respondent)) - responseBind = wire.Bind(new(model.IResponse), new(*model.Response)) - scaleLabelBind = wire.Bind(new(model.IScaleLabel), new(*model.ScaleLabel)) - targetBind = wire.Bind(new(model.ITarget), new(*model.Target)) - validationBind = wire.Bind(new(model.IValidation), new(*model.Validation)) - transactionBind = wire.Bind(new(model.ITransaction), new(*model.Transaction)) - - webhookBind = wire.Bind(new(traq.IWebhook), new(*traq.Webhook)) + administratorBind = wire.Bind(new(model.IAdministrator), new(*model.Administrator)) + administratorGroupBind = wire.Bind(new(model.IAdministratorGroup), new(*model.AdministratorGroup)) + administratorUserBind = wire.Bind(new(model.IAdministratorUser), new(*model.AdministratorUser)) + optionBind = wire.Bind(new(model.IOption), new(*model.Option)) + questionnaireBind = wire.Bind(new(model.IQuestionnaire), new(*model.Questionnaire)) + questionBind = wire.Bind(new(model.IQuestion), new(*model.Question)) + respondentBind = wire.Bind(new(model.IRespondent), new(*model.Respondent)) + responseBind = wire.Bind(new(model.IResponse), new(*model.Response)) + scaleLabelBind = wire.Bind(new(model.IScaleLabel), new(*model.ScaleLabel)) + targetBind = wire.Bind(new(model.ITarget), new(*model.Target)) + targetGroupBind = wire.Bind(new(model.ITargetGroup), new(*model.TargetGroup)) + targetUserBind = wire.Bind(new(model.ITargetUser), new(*model.TargetUser)) + validationBind = wire.Bind(new(model.IValidation), new(*model.Validation)) + transactionBind = wire.Bind(new(model.ITransaction), new(*model.Transaction)) + webhookBind = wire.Bind(new(traq.IWebhook), new(*traq.Webhook)) ) func InjectAPIServer() *handler.Handler { @@ -33,6 +36,8 @@ func InjectAPIServer() *handler.Handler { controller.NewQuestionnaire, controller.NewMiddleware, model.NewAdministrator, + model.NewAdministratorGroup, + model.NewAdministratorUser, model.NewOption, model.NewQuestionnaire, model.NewQuestion, @@ -40,10 +45,14 @@ func InjectAPIServer() *handler.Handler { model.NewResponse, model.NewScaleLabel, model.NewTarget, + model.NewTargetGroup, + model.NewTargetUser, model.NewValidation, model.NewTransaction, traq.NewWebhook, administratorBind, + administratorGroupBind, + administratorUserBind, optionBind, questionnaireBind, questionBind, @@ -51,6 +60,8 @@ func InjectAPIServer() *handler.Handler { responseBind, scaleLabelBind, targetBind, + targetGroupBind, + targetUserBind, validationBind, transactionBind, webhookBind, diff --git a/wire_gen.go b/wire_gen.go index 7a311489..8956d63c 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -1,6 +1,6 @@ // Code generated by Wire. DO NOT EDIT. -//go:generate go run -mod=mod github.com/google/wire/cmd/wire +//go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject @@ -23,17 +23,21 @@ import ( func InjectAPIServer() *handler.Handler { questionnaire := model.NewQuestionnaire() target := model.NewTarget() + targetGroup := model.NewTargetGroup() + targetUser := model.NewTargetUser() administrator := model.NewAdministrator() + administratorGroup := model.NewAdministratorGroup() + administratorUser := model.NewAdministratorUser() question := model.NewQuestion() option := model.NewOption() scaleLabel := model.NewScaleLabel() validation := model.NewValidation() transaction := model.NewTransaction() - webhook := traq.NewWebhook() - controllerQuestionnaire := controller.NewQuestionnaire(questionnaire, target, administrator, question, option, scaleLabel, validation, transaction, webhook) respondent := model.NewRespondent() + webhook := traq.NewWebhook() response := model.NewResponse() controllerResponse := controller.NewResponse(questionnaire, respondent, response, target, question, validation, scaleLabel) + controllerQuestionnaire := controller.NewQuestionnaire(questionnaire, target, targetGroup, targetUser, administrator, administratorGroup, administratorUser, question, option, scaleLabel, validation, transaction, respondent, webhook, controllerResponse) middleware := controller.NewMiddleware(administrator, respondent, question, questionnaire) handlerHandler := handler.NewHandler(controllerQuestionnaire, controllerResponse, middleware) return handlerHandler @@ -42,16 +46,19 @@ func InjectAPIServer() *handler.Handler { // wire.go: var ( - administratorBind = wire.Bind(new(model.IAdministrator), new(*model.Administrator)) - optionBind = wire.Bind(new(model.IOption), new(*model.Option)) - questionnaireBind = wire.Bind(new(model.IQuestionnaire), new(*model.Questionnaire)) - questionBind = wire.Bind(new(model.IQuestion), new(*model.Question)) - respondentBind = wire.Bind(new(model.IRespondent), new(*model.Respondent)) - responseBind = wire.Bind(new(model.IResponse), new(*model.Response)) - scaleLabelBind = wire.Bind(new(model.IScaleLabel), new(*model.ScaleLabel)) - targetBind = wire.Bind(new(model.ITarget), new(*model.Target)) - validationBind = wire.Bind(new(model.IValidation), new(*model.Validation)) - transactionBind = wire.Bind(new(model.ITransaction), new(*model.Transaction)) - - webhookBind = wire.Bind(new(traq.IWebhook), new(*traq.Webhook)) + administratorBind = wire.Bind(new(model.IAdministrator), new(*model.Administrator)) + administratorGroupBind = wire.Bind(new(model.IAdministratorGroup), new(*model.AdministratorGroup)) + administratorUserBind = wire.Bind(new(model.IAdministratorUser), new(*model.AdministratorUser)) + optionBind = wire.Bind(new(model.IOption), new(*model.Option)) + questionnaireBind = wire.Bind(new(model.IQuestionnaire), new(*model.Questionnaire)) + questionBind = wire.Bind(new(model.IQuestion), new(*model.Question)) + respondentBind = wire.Bind(new(model.IRespondent), new(*model.Respondent)) + responseBind = wire.Bind(new(model.IResponse), new(*model.Response)) + scaleLabelBind = wire.Bind(new(model.IScaleLabel), new(*model.ScaleLabel)) + targetBind = wire.Bind(new(model.ITarget), new(*model.Target)) + targetGroupBind = wire.Bind(new(model.ITargetGroup), new(*model.TargetGroup)) + targetUserBind = wire.Bind(new(model.ITargetUser), new(*model.TargetUser)) + validationBind = wire.Bind(new(model.IValidation), new(*model.Validation)) + transactionBind = wire.Bind(new(model.ITransaction), new(*model.Transaction)) + webhookBind = wire.Bind(new(traq.IWebhook), new(*traq.Webhook)) )