diff --git a/generated/api.gen.go b/generated/api.gen.go index bc5bd92..d3a3f47 100644 --- a/generated/api.gen.go +++ b/generated/api.gen.go @@ -138,7 +138,7 @@ type AcademicServiceCourseRegistrationRequest struct { UserId string `json:"userId"` } -// AcademicServiceFaculty 教員 +// AcademicServiceFaculty defines model for AcademicService.Faculty. type AcademicServiceFaculty struct { Email string `json:"email"` Id string `json:"id"` @@ -151,6 +151,13 @@ type AcademicServiceFacultyRequest struct { Name string `json:"name"` } +// AcademicServicePersonalCalendarItem defines model for AcademicService.PersonalCalendarItem. +type AcademicServicePersonalCalendarItem struct { + Date time.Time `json:"date"` + Slot DottoFoundationV1TimetableSlot `json:"slot"` + TimetableItem AcademicServiceTimetableItem `json:"timetableItem"` +} + // AcademicServiceReservation defines model for AcademicService.Reservation. type AcademicServiceReservation struct { EndAt time.Time `json:"endAt"` @@ -194,7 +201,6 @@ type AcademicServiceSubject struct { // AcademicServiceSubjectFaculty defines model for AcademicService.SubjectFaculty. type AcademicServiceSubjectFaculty struct { - // Faculty 教員 Faculty AcademicServiceFaculty `json:"faculty"` IsPrimary bool `json:"isPrimary"` } @@ -231,17 +237,18 @@ type AcademicServiceSubjectTargetClass struct { // AcademicServiceTimetableItem defines model for AcademicService.TimetableItem. type AcademicServiceTimetableItem struct { - DayOfWeek DottoFoundationV1DayOfWeek `json:"dayOfWeek"` - Id string `json:"id"` - Period DottoFoundationV1Period `json:"period"` - Subject AcademicServiceSubjectSummary `json:"subject"` + Id string `json:"id"` + Rooms []AcademicServiceRoom `json:"rooms"` + + // Slot 集中講義など、時間割に含まれていない場合はnull + Slot *DottoFoundationV1TimetableSlot `json:"slot,omitempty"` + Subject AcademicServiceSubjectSummary `json:"subject"` } // AcademicServiceTimetableItemRequest defines model for AcademicService.TimetableItemRequest. type AcademicServiceTimetableItemRequest struct { - DayOfWeek DottoFoundationV1DayOfWeek `json:"dayOfWeek"` - Period DottoFoundationV1Period `json:"period"` - SubjectId string `json:"subjectId"` + Slot *DottoFoundationV1TimetableSlot `json:"slot,omitempty"` + SubjectId string `json:"subjectId"` } // AnnouncementServiceAnnouncement defines model for AnnouncementService.Announcement. @@ -291,6 +298,12 @@ type DottoFoundationV1SubjectClassification string // DottoFoundationV1SubjectRequirementType 必修・選択 type DottoFoundationV1SubjectRequirementType string +// DottoFoundationV1TimetableSlot defines model for DottoFoundationV1.TimetableSlot. +type DottoFoundationV1TimetableSlot struct { + DayOfWeek DottoFoundationV1DayOfWeek `json:"dayOfWeek"` + Period DottoFoundationV1Period `json:"period"` +} + // UserServiceUser defines model for UserService.User. type UserServiceUser struct { // Class クラス @@ -317,8 +330,17 @@ type CourseRegistrationsV1ListParams struct { // Year 開講年度; 指定しない場合は今年度が選択される Year *int `form:"year,omitempty" json:"year,omitempty"` - // Semester 開講時期 - Semester DottoFoundationV1CourseSemester `form:"semester" json:"semester"` + // Semesters 開講時期 + Semesters []DottoFoundationV1CourseSemester `form:"semesters" json:"semesters"` +} + +// PersonalCalendarItemsV1ListParams defines parameters for PersonalCalendarItemsV1List. +type PersonalCalendarItemsV1ListParams struct { + // UserId ユーザーID + UserId string `form:"userId" json:"userId"` + + // Dates 日付のリスト; 指定した日付の個人カレンダーアイテムのみを取得する + Dates []time.Time `form:"dates" json:"dates"` } // RoomsV1ListParams defines parameters for RoomsV1List. @@ -340,29 +362,29 @@ type SubjectsV1ListParams struct { // Q 検索ワード Q *string `form:"q,omitempty" json:"q,omitempty"` - // Grade 学年 - Grade *[]DottoFoundationV1Grade `form:"grade,omitempty" json:"grade,omitempty"` + // Grades 学年 + Grades *[]DottoFoundationV1Grade `form:"grades,omitempty" json:"grades,omitempty"` // Courses コース; 大学院の場合は大学院コースに読み替え Courses *[]DottoFoundationV1Course `form:"courses,omitempty" json:"courses,omitempty"` - // Class クラス; 大学院の学年を選択した場合は選択できない - Class *[]DottoFoundationV1Class `form:"class,omitempty" json:"class,omitempty"` + // Classes クラス; 大学院の学年を選択した場合は選択できない + Classes *[]DottoFoundationV1Class `form:"classes,omitempty" json:"classes,omitempty"` - // Classification 学部: 専門・教養; 大学院: 専門・研究指導 - Classification *[]DottoFoundationV1SubjectClassification `form:"classification,omitempty" json:"classification,omitempty"` + // Classifications 学部: 専門・教養; 大学院: 専門・研究指導 + Classifications *[]DottoFoundationV1SubjectClassification `form:"classifications,omitempty" json:"classifications,omitempty"` // Year 開講年度; 指定しない場合は今年度が選択される Year *int `form:"year,omitempty" json:"year,omitempty"` - // Semester 開講時期 - Semester *[]DottoFoundationV1CourseSemester `form:"semester,omitempty" json:"semester,omitempty"` + // Semesters 開講時期 + Semesters *[]DottoFoundationV1CourseSemester `form:"semesters,omitempty" json:"semesters,omitempty"` - // RequirementType 必修・選択・選択必修 - RequirementType *[]DottoFoundationV1SubjectRequirementType `form:"requirementType,omitempty" json:"requirementType,omitempty"` + // RequirementTypes 必修・選択・選択必修 + RequirementTypes *[]DottoFoundationV1SubjectRequirementType `form:"requirementTypes,omitempty" json:"requirementTypes,omitempty"` - // CulturalSubjectCategory 教養科目カテゴリ - CulturalSubjectCategory *[]DottoFoundationV1CulturalSubjectCategory `form:"culturalSubjectCategory,omitempty" json:"culturalSubjectCategory,omitempty"` + // CulturalSubjectCategories 教養科目カテゴリ + CulturalSubjectCategories *[]DottoFoundationV1CulturalSubjectCategory `form:"culturalSubjectCategories,omitempty" json:"culturalSubjectCategories,omitempty"` } // TimetableItemsV1ListParams defines parameters for TimetableItemsV1List. @@ -370,8 +392,8 @@ type TimetableItemsV1ListParams struct { // Year 開講年度; 指定しない場合は今年度が選択される Year *int `form:"year,omitempty" json:"year,omitempty"` - // Semester 開講時期 - Semester DottoFoundationV1CourseSemester `form:"semester" json:"semester"` + // Semesters 開講時期 + Semesters []DottoFoundationV1CourseSemester `form:"semesters" json:"semesters"` // DayOfWeek 曜日; 複数指定時はORでフィルタリングされる; 指定しない場合は全ての曜日が選択される DayOfWeek *[]DottoFoundationV1DayOfWeek `form:"dayOfWeek,omitempty" json:"dayOfWeek,omitempty"` @@ -446,6 +468,9 @@ type ServerInterface interface { // (PUT /v1/faculties/{id}) FacultiesV1Update(c *gin.Context, id string) + // (GET /v1/personalCalendarItems) + PersonalCalendarItemsV1List(c *gin.Context, params PersonalCalendarItemsV1ListParams) + // (GET /v1/rooms) RoomsV1List(c *gin.Context, params RoomsV1ListParams) @@ -639,18 +664,18 @@ func (siw *ServerInterfaceWrapper) CourseRegistrationsV1List(c *gin.Context) { return } - // ------------- Required query parameter "semester" ------------- + // ------------- Required query parameter "semesters" ------------- - if paramValue := c.Query("semester"); paramValue != "" { + if paramValue := c.Query("semesters"); paramValue != "" { } else { - siw.ErrorHandler(c, fmt.Errorf("Query argument semester is required, but not found"), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Query argument semesters is required, but not found"), http.StatusBadRequest) return } - err = runtime.BindQueryParameter("form", false, true, "semester", c.Request.URL.Query(), ¶ms.Semester) + err = runtime.BindQueryParameter("form", false, true, "semesters", c.Request.URL.Query(), ¶ms.Semesters) if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter semester: %w", err), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter semesters: %w", err), http.StatusBadRequest) return } @@ -813,6 +838,56 @@ func (siw *ServerInterfaceWrapper) FacultiesV1Update(c *gin.Context) { siw.Handler.FacultiesV1Update(c, id) } +// PersonalCalendarItemsV1List operation middleware +func (siw *ServerInterfaceWrapper) PersonalCalendarItemsV1List(c *gin.Context) { + + var err error + + c.Set(BearerAuthScopes, []string{}) + + // Parameter object where we will unmarshal all parameters from the context + var params PersonalCalendarItemsV1ListParams + + // ------------- Required query parameter "userId" ------------- + + if paramValue := c.Query("userId"); paramValue != "" { + + } else { + siw.ErrorHandler(c, fmt.Errorf("Query argument userId is required, but not found"), http.StatusBadRequest) + return + } + + err = runtime.BindQueryParameter("form", false, true, "userId", c.Request.URL.Query(), ¶ms.UserId) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter userId: %w", err), http.StatusBadRequest) + return + } + + // ------------- Required query parameter "dates" ------------- + + if paramValue := c.Query("dates"); paramValue != "" { + + } else { + siw.ErrorHandler(c, fmt.Errorf("Query argument dates is required, but not found"), http.StatusBadRequest) + return + } + + err = runtime.BindQueryParameter("form", false, true, "dates", c.Request.URL.Query(), ¶ms.Dates) + if err != nil { + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter dates: %w", err), http.StatusBadRequest) + return + } + + for _, middleware := range siw.HandlerMiddlewares { + middleware(c) + if c.IsAborted() { + return + } + } + + siw.Handler.PersonalCalendarItemsV1List(c, params) +} + // RoomsV1List operation middleware func (siw *ServerInterfaceWrapper) RoomsV1List(c *gin.Context) { @@ -997,11 +1072,11 @@ func (siw *ServerInterfaceWrapper) SubjectsV1List(c *gin.Context) { return } - // ------------- Optional query parameter "grade" ------------- + // ------------- Optional query parameter "grades" ------------- - err = runtime.BindQueryParameter("form", false, false, "grade", c.Request.URL.Query(), ¶ms.Grade) + err = runtime.BindQueryParameter("form", false, false, "grades", c.Request.URL.Query(), ¶ms.Grades) if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter grade: %w", err), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter grades: %w", err), http.StatusBadRequest) return } @@ -1013,19 +1088,19 @@ func (siw *ServerInterfaceWrapper) SubjectsV1List(c *gin.Context) { return } - // ------------- Optional query parameter "class" ------------- + // ------------- Optional query parameter "classes" ------------- - err = runtime.BindQueryParameter("form", false, false, "class", c.Request.URL.Query(), ¶ms.Class) + err = runtime.BindQueryParameter("form", false, false, "classes", c.Request.URL.Query(), ¶ms.Classes) if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter class: %w", err), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter classes: %w", err), http.StatusBadRequest) return } - // ------------- Optional query parameter "classification" ------------- + // ------------- Optional query parameter "classifications" ------------- - err = runtime.BindQueryParameter("form", false, false, "classification", c.Request.URL.Query(), ¶ms.Classification) + err = runtime.BindQueryParameter("form", false, false, "classifications", c.Request.URL.Query(), ¶ms.Classifications) if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter classification: %w", err), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter classifications: %w", err), http.StatusBadRequest) return } @@ -1037,27 +1112,27 @@ func (siw *ServerInterfaceWrapper) SubjectsV1List(c *gin.Context) { return } - // ------------- Optional query parameter "semester" ------------- + // ------------- Optional query parameter "semesters" ------------- - err = runtime.BindQueryParameter("form", false, false, "semester", c.Request.URL.Query(), ¶ms.Semester) + err = runtime.BindQueryParameter("form", false, false, "semesters", c.Request.URL.Query(), ¶ms.Semesters) if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter semester: %w", err), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter semesters: %w", err), http.StatusBadRequest) return } - // ------------- Optional query parameter "requirementType" ------------- + // ------------- Optional query parameter "requirementTypes" ------------- - err = runtime.BindQueryParameter("form", false, false, "requirementType", c.Request.URL.Query(), ¶ms.RequirementType) + err = runtime.BindQueryParameter("form", false, false, "requirementTypes", c.Request.URL.Query(), ¶ms.RequirementTypes) if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter requirementType: %w", err), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter requirementTypes: %w", err), http.StatusBadRequest) return } - // ------------- Optional query parameter "culturalSubjectCategory" ------------- + // ------------- Optional query parameter "culturalSubjectCategories" ------------- - err = runtime.BindQueryParameter("form", false, false, "culturalSubjectCategory", c.Request.URL.Query(), ¶ms.CulturalSubjectCategory) + err = runtime.BindQueryParameter("form", false, false, "culturalSubjectCategories", c.Request.URL.Query(), ¶ms.CulturalSubjectCategories) if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter culturalSubjectCategory: %w", err), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter culturalSubjectCategories: %w", err), http.StatusBadRequest) return } @@ -1156,18 +1231,18 @@ func (siw *ServerInterfaceWrapper) TimetableItemsV1List(c *gin.Context) { return } - // ------------- Required query parameter "semester" ------------- + // ------------- Required query parameter "semesters" ------------- - if paramValue := c.Query("semester"); paramValue != "" { + if paramValue := c.Query("semesters"); paramValue != "" { } else { - siw.ErrorHandler(c, fmt.Errorf("Query argument semester is required, but not found"), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Query argument semesters is required, but not found"), http.StatusBadRequest) return } - err = runtime.BindQueryParameter("form", false, true, "semester", c.Request.URL.Query(), ¶ms.Semester) + err = runtime.BindQueryParameter("form", false, true, "semesters", c.Request.URL.Query(), ¶ms.Semesters) if err != nil { - siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter semester: %w", err), http.StatusBadRequest) + siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter semesters: %w", err), http.StatusBadRequest) return } @@ -1296,6 +1371,7 @@ func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options router.DELETE(options.BaseURL+"/v1/faculties/:id", wrapper.FacultiesV1Delete) router.GET(options.BaseURL+"/v1/faculties/:id", wrapper.FacultiesV1Detail) router.PUT(options.BaseURL+"/v1/faculties/:id", wrapper.FacultiesV1Update) + router.GET(options.BaseURL+"/v1/personalCalendarItems", wrapper.PersonalCalendarItemsV1List) router.GET(options.BaseURL+"/v1/rooms", wrapper.RoomsV1List) router.POST(options.BaseURL+"/v1/rooms", wrapper.RoomsV1Create) router.DELETE(options.BaseURL+"/v1/rooms/:id", wrapper.RoomsV1Delete) @@ -1589,7 +1665,6 @@ type FacultiesV1CreateResponseObject interface { } type FacultiesV1Create201JSONResponse struct { - // Faculty 教員 Faculty AcademicServiceFaculty `json:"faculty"` } @@ -1649,7 +1724,6 @@ type FacultiesV1DetailResponseObject interface { } type FacultiesV1Detail200JSONResponse struct { - // Faculty 教員 Faculty AcademicServiceFaculty `json:"faculty"` } @@ -1686,7 +1760,6 @@ type FacultiesV1UpdateResponseObject interface { } type FacultiesV1Update200JSONResponse struct { - // Faculty 教員 Faculty AcademicServiceFaculty `json:"faculty"` } @@ -1713,6 +1786,25 @@ func (response FacultiesV1Update404Response) VisitFacultiesV1UpdateResponse(w ht return nil } +type PersonalCalendarItemsV1ListRequestObject struct { + Params PersonalCalendarItemsV1ListParams +} + +type PersonalCalendarItemsV1ListResponseObject interface { + VisitPersonalCalendarItemsV1ListResponse(w http.ResponseWriter) error +} + +type PersonalCalendarItemsV1List200JSONResponse struct { + PersonalCalendarItems []AcademicServicePersonalCalendarItem `json:"personalCalendarItems"` +} + +func (response PersonalCalendarItemsV1List200JSONResponse) VisitPersonalCalendarItemsV1ListResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + type RoomsV1ListRequestObject struct { Params RoomsV1ListParams } @@ -2182,6 +2274,9 @@ type StrictServerInterface interface { // (PUT /v1/faculties/{id}) FacultiesV1Update(ctx context.Context, request FacultiesV1UpdateRequestObject) (FacultiesV1UpdateResponseObject, error) + // (GET /v1/personalCalendarItems) + PersonalCalendarItemsV1List(ctx context.Context, request PersonalCalendarItemsV1ListRequestObject) (PersonalCalendarItemsV1ListResponseObject, error) + // (GET /v1/rooms) RoomsV1List(ctx context.Context, request RoomsV1ListRequestObject) (RoomsV1ListResponseObject, error) @@ -2618,6 +2713,33 @@ func (sh *strictHandler) FacultiesV1Update(ctx *gin.Context, id string) { } } +// PersonalCalendarItemsV1List operation middleware +func (sh *strictHandler) PersonalCalendarItemsV1List(ctx *gin.Context, params PersonalCalendarItemsV1ListParams) { + var request PersonalCalendarItemsV1ListRequestObject + + request.Params = params + + handler := func(ctx *gin.Context, request interface{}) (interface{}, error) { + return sh.ssi.PersonalCalendarItemsV1List(ctx, request.(PersonalCalendarItemsV1ListRequestObject)) + } + for _, middleware := range sh.middlewares { + handler = middleware(handler, "PersonalCalendarItemsV1List") + } + + response, err := handler(ctx, request) + + if err != nil { + ctx.Error(err) + ctx.Status(http.StatusInternalServerError) + } else if validResponse, ok := response.(PersonalCalendarItemsV1ListResponseObject); ok { + if err := validResponse.VisitPersonalCalendarItemsV1ListResponse(ctx.Writer); err != nil { + ctx.Error(err) + } + } else if response != nil { + ctx.Error(fmt.Errorf("unexpected response type: %T", response)) + } +} + // RoomsV1List operation middleware func (sh *strictHandler) RoomsV1List(ctx *gin.Context, params RoomsV1ListParams) { var request RoomsV1ListRequestObject diff --git a/generated/external/academic_api/client.gen.go b/generated/external/academic_api/client.gen.go index dcb2818..0ab5420 100644 --- a/generated/external/academic_api/client.gen.go +++ b/generated/external/academic_api/client.gen.go @@ -166,7 +166,13 @@ type DottoFoundationV1SubjectClassification string // DottoFoundationV1SubjectRequirementType 必修・選択 type DottoFoundationV1SubjectRequirementType string -// Faculty 教員 +// DottoFoundationV1TimetableSlot defines model for DottoFoundationV1.TimetableSlot. +type DottoFoundationV1TimetableSlot struct { + DayOfWeek DottoFoundationV1DayOfWeek `json:"dayOfWeek"` + Period DottoFoundationV1Period `json:"period"` +} + +// Faculty defines model for Faculty. type Faculty struct { Email string `json:"email"` Id string `json:"id"` @@ -179,6 +185,13 @@ type FacultyRequest struct { Name string `json:"name"` } +// PersonalCalendarItem defines model for PersonalCalendarItem. +type PersonalCalendarItem struct { + Date time.Time `json:"date"` + Slot DottoFoundationV1TimetableSlot `json:"slot"` + TimetableItem TimetableItem `json:"timetableItem"` +} + // Reservation defines model for Reservation. type Reservation struct { EndAt time.Time `json:"endAt"` @@ -222,7 +235,6 @@ type Subject struct { // SubjectFaculty defines model for SubjectFaculty. type SubjectFaculty struct { - // Faculty 教員 Faculty Faculty `json:"faculty"` IsPrimary bool `json:"isPrimary"` } @@ -343,17 +355,18 @@ type Syllabus struct { // TimetableItem defines model for TimetableItem. type TimetableItem struct { - DayOfWeek DottoFoundationV1DayOfWeek `json:"dayOfWeek"` - Id string `json:"id"` - Period DottoFoundationV1Period `json:"period"` - Subject SubjectSummary `json:"subject"` + Id string `json:"id"` + Rooms []Room `json:"rooms"` + + // Slot 集中講義など、時間割に含まれていない場合はnull + Slot *DottoFoundationV1TimetableSlot `json:"slot,omitempty"` + Subject SubjectSummary `json:"subject"` } // TimetableItemRequest defines model for TimetableItemRequest. type TimetableItemRequest struct { - DayOfWeek DottoFoundationV1DayOfWeek `json:"dayOfWeek"` - Period DottoFoundationV1Period `json:"period"` - SubjectId string `json:"subjectId"` + Slot *DottoFoundationV1TimetableSlot `json:"slot,omitempty"` + SubjectId string `json:"subjectId"` } // CourseRegistrationsV1ListParams defines parameters for CourseRegistrationsV1List. @@ -364,8 +377,8 @@ type CourseRegistrationsV1ListParams struct { // Year 開講年度; 指定しない場合は今年度が選択される Year *int `form:"year,omitempty" json:"year,omitempty"` - // Semester 開講時期 - Semester DottoFoundationV1CourseSemester `form:"semester" json:"semester"` + // Semesters 開講時期; 指定された時期に開講される全ての科目が取得される + Semesters []DottoFoundationV1CourseSemester `form:"semesters" json:"semesters"` } // FacultiesV1ListParams defines parameters for FacultiesV1List. @@ -374,6 +387,15 @@ type FacultiesV1ListParams struct { Ids *[]string `form:"ids,omitempty" json:"ids,omitempty"` } +// PersonalCalendarItemsV1ListParams defines parameters for PersonalCalendarItemsV1List. +type PersonalCalendarItemsV1ListParams struct { + // UserId ユーザーID + UserId string `form:"userId" json:"userId"` + + // Dates 日付のリスト; 指定した日付の個人カレンダーアイテムのみを取得する + Dates []time.Time `form:"dates" json:"dates"` +} + // RoomsV1ListParams defines parameters for RoomsV1List. type RoomsV1ListParams struct { // Ids 教室IDのリスト; 指定した場合は指定した教室IDのみを取得する @@ -400,29 +422,29 @@ type SubjectsV1ListParams struct { // Q 検索ワード Q *string `form:"q,omitempty" json:"q,omitempty"` - // Grade 学年 - Grade *[]DottoFoundationV1Grade `form:"grade,omitempty" json:"grade,omitempty"` + // Grades 学年 + Grades *[]DottoFoundationV1Grade `form:"grades,omitempty" json:"grades,omitempty"` // Courses コース; 大学院の場合は大学院コースに読み替え Courses *[]DottoFoundationV1Course `form:"courses,omitempty" json:"courses,omitempty"` - // Class クラス; 大学院の学年を選択した場合は選択できない - Class *[]DottoFoundationV1Class `form:"class,omitempty" json:"class,omitempty"` + // Classes クラス; 大学院の学年を選択した場合は選択できない + Classes *[]DottoFoundationV1Class `form:"classes,omitempty" json:"classes,omitempty"` - // Classification 学部: 専門・教養; 大学院: 専門・研究指導 - Classification *[]DottoFoundationV1SubjectClassification `form:"classification,omitempty" json:"classification,omitempty"` + // Classifications 学部: 専門・教養; 大学院: 専門・研究指導 + Classifications *[]DottoFoundationV1SubjectClassification `form:"classifications,omitempty" json:"classifications,omitempty"` // Year 開講年度; 指定しない場合は今年度が選択される Year *int `form:"year,omitempty" json:"year,omitempty"` - // Semester 開講時期 - Semester *[]DottoFoundationV1CourseSemester `form:"semester,omitempty" json:"semester,omitempty"` + // Semesters 開講時期 + Semesters *[]DottoFoundationV1CourseSemester `form:"semesters,omitempty" json:"semesters,omitempty"` - // RequirementType 必修・選択・選択必修 - RequirementType *[]DottoFoundationV1SubjectRequirementType `form:"requirementType,omitempty" json:"requirementType,omitempty"` + // RequirementTypes 必修・選択・選択必修 + RequirementTypes *[]DottoFoundationV1SubjectRequirementType `form:"requirementTypes,omitempty" json:"requirementTypes,omitempty"` - // CulturalSubjectCategory 教養科目カテゴリ - CulturalSubjectCategory *[]DottoFoundationV1CulturalSubjectCategory `form:"culturalSubjectCategory,omitempty" json:"culturalSubjectCategory,omitempty"` + // CulturalSubjectCategories 教養科目カテゴリ + CulturalSubjectCategories *[]DottoFoundationV1CulturalSubjectCategory `form:"culturalSubjectCategories,omitempty" json:"culturalSubjectCategories,omitempty"` } // TimetableItemsV1ListParams defines parameters for TimetableItemsV1List. @@ -430,11 +452,8 @@ type TimetableItemsV1ListParams struct { // Year 開講年度; 指定しない場合は今年度が選択される Year *int `form:"year,omitempty" json:"year,omitempty"` - // Semester 開講時期 - Semester DottoFoundationV1CourseSemester `form:"semester" json:"semester"` - - // DayOfWeek 曜日; 複数指定時はORでフィルタリングされる; 指定しない場合は全ての曜日が選択される - DayOfWeek *[]DottoFoundationV1DayOfWeek `form:"dayOfWeek,omitempty" json:"dayOfWeek,omitempty"` + // Semesters 開講時期; 指定された時期に開講される全ての科目が取得される + Semesters []DottoFoundationV1CourseSemester `form:"semesters" json:"semesters"` } // CourseRegistrationsV1CreateJSONRequestBody defines body for CourseRegistrationsV1Create for application/json ContentType. @@ -561,6 +580,9 @@ type ClientInterface interface { FacultiesV1Update(ctx context.Context, id string, body FacultiesV1UpdateJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // PersonalCalendarItemsV1List request + PersonalCalendarItemsV1List(ctx context.Context, params *PersonalCalendarItemsV1ListParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // RoomsV1List request RoomsV1List(ctx context.Context, params *RoomsV1ListParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -744,6 +766,18 @@ func (c *Client) FacultiesV1Update(ctx context.Context, id string, body Facultie return c.Client.Do(req) } +func (c *Client) PersonalCalendarItemsV1List(ctx context.Context, params *PersonalCalendarItemsV1ListParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPersonalCalendarItemsV1ListRequest(c.Server, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) RoomsV1List(ctx context.Context, params *RoomsV1ListParams, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewRoomsV1ListRequest(c.Server, params) if err != nil { @@ -1010,7 +1044,7 @@ func NewCourseRegistrationsV1ListRequest(server string, params *CourseRegistrati } - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "semester", runtime.ParamLocationQuery, params.Semester); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "semesters", runtime.ParamLocationQuery, params.Semesters); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -1311,6 +1345,63 @@ func NewFacultiesV1UpdateRequestWithBody(server string, id string, contentType s return req, nil } +// NewPersonalCalendarItemsV1ListRequest generates requests for PersonalCalendarItemsV1List +func NewPersonalCalendarItemsV1ListRequest(server string, params *PersonalCalendarItemsV1ListParams) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/personalCalendarItems") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + if params != nil { + queryValues := queryURL.Query() + + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "userId", runtime.ParamLocationQuery, params.UserId); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "dates", runtime.ParamLocationQuery, params.Dates); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + queryURL.RawQuery = queryValues.Encode() + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewRoomsV1ListRequest generates requests for RoomsV1List func NewRoomsV1ListRequest(server string, params *RoomsV1ListParams) (*http.Request, error) { var err error @@ -1657,9 +1748,9 @@ func NewSubjectsV1ListRequest(server string, params *SubjectsV1ListParams) (*htt } - if params.Grade != nil { + if params.Grades != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "grade", runtime.ParamLocationQuery, *params.Grade); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "grades", runtime.ParamLocationQuery, *params.Grades); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -1689,9 +1780,9 @@ func NewSubjectsV1ListRequest(server string, params *SubjectsV1ListParams) (*htt } - if params.Class != nil { + if params.Classes != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "class", runtime.ParamLocationQuery, *params.Class); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "classes", runtime.ParamLocationQuery, *params.Classes); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -1705,9 +1796,9 @@ func NewSubjectsV1ListRequest(server string, params *SubjectsV1ListParams) (*htt } - if params.Classification != nil { + if params.Classifications != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "classification", runtime.ParamLocationQuery, *params.Classification); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "classifications", runtime.ParamLocationQuery, *params.Classifications); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -1737,9 +1828,9 @@ func NewSubjectsV1ListRequest(server string, params *SubjectsV1ListParams) (*htt } - if params.Semester != nil { + if params.Semesters != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "semester", runtime.ParamLocationQuery, *params.Semester); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "semesters", runtime.ParamLocationQuery, *params.Semesters); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -1753,9 +1844,9 @@ func NewSubjectsV1ListRequest(server string, params *SubjectsV1ListParams) (*htt } - if params.RequirementType != nil { + if params.RequirementTypes != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "requirementType", runtime.ParamLocationQuery, *params.RequirementType); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "requirementTypes", runtime.ParamLocationQuery, *params.RequirementTypes); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -1769,9 +1860,9 @@ func NewSubjectsV1ListRequest(server string, params *SubjectsV1ListParams) (*htt } - if params.CulturalSubjectCategory != nil { + if params.CulturalSubjectCategories != nil { - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "culturalSubjectCategory", runtime.ParamLocationQuery, *params.CulturalSubjectCategory); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "culturalSubjectCategories", runtime.ParamLocationQuery, *params.CulturalSubjectCategories); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -1976,7 +2067,7 @@ func NewTimetableItemsV1ListRequest(server string, params *TimetableItemsV1ListP } - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "semester", runtime.ParamLocationQuery, params.Semester); err != nil { + if queryFrag, err := runtime.StyleParamWithLocation("form", false, "semesters", runtime.ParamLocationQuery, params.Semesters); err != nil { return nil, err } else if parsed, err := url.ParseQuery(queryFrag); err != nil { return nil, err @@ -1988,22 +2079,6 @@ func NewTimetableItemsV1ListRequest(server string, params *TimetableItemsV1ListP } } - if params.DayOfWeek != nil { - - if queryFrag, err := runtime.StyleParamWithLocation("form", false, "dayOfWeek", runtime.ParamLocationQuery, *params.DayOfWeek); err != nil { - return nil, err - } else if parsed, err := url.ParseQuery(queryFrag); err != nil { - return nil, err - } else { - for k, v := range parsed { - for _, v2 := range v { - queryValues.Add(k, v2) - } - } - } - - } - queryURL.RawQuery = queryValues.Encode() } @@ -2162,6 +2237,9 @@ type ClientWithResponsesInterface interface { FacultiesV1UpdateWithResponse(ctx context.Context, id string, body FacultiesV1UpdateJSONRequestBody, reqEditors ...RequestEditorFn) (*FacultiesV1UpdateResponse, error) + // PersonalCalendarItemsV1ListWithResponse request + PersonalCalendarItemsV1ListWithResponse(ctx context.Context, params *PersonalCalendarItemsV1ListParams, reqEditors ...RequestEditorFn) (*PersonalCalendarItemsV1ListResponse, error) + // RoomsV1ListWithResponse request RoomsV1ListWithResponse(ctx context.Context, params *RoomsV1ListParams, reqEditors ...RequestEditorFn) (*RoomsV1ListResponse, error) @@ -2310,7 +2388,6 @@ type FacultiesV1CreateResponse struct { Body []byte HTTPResponse *http.Response JSON201 *struct { - // Faculty 教員 Faculty Faculty `json:"faculty"` } } @@ -2356,7 +2433,6 @@ type FacultiesV1DetailResponse struct { Body []byte HTTPResponse *http.Response JSON200 *struct { - // Faculty 教員 Faculty Faculty `json:"faculty"` } } @@ -2381,7 +2457,6 @@ type FacultiesV1UpdateResponse struct { Body []byte HTTPResponse *http.Response JSON200 *struct { - // Faculty 教員 Faculty Faculty `json:"faculty"` } } @@ -2402,6 +2477,30 @@ func (r FacultiesV1UpdateResponse) StatusCode() int { return 0 } +type PersonalCalendarItemsV1ListResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + PersonalCalendarItems []PersonalCalendarItem `json:"personalCalendarItems"` + } +} + +// Status returns HTTPResponse.Status +func (r PersonalCalendarItemsV1ListResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r PersonalCalendarItemsV1ListResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type RoomsV1ListResponse struct { Body []byte HTTPResponse *http.Response @@ -2825,6 +2924,15 @@ func (c *ClientWithResponses) FacultiesV1UpdateWithResponse(ctx context.Context, return ParseFacultiesV1UpdateResponse(rsp) } +// PersonalCalendarItemsV1ListWithResponse request returning *PersonalCalendarItemsV1ListResponse +func (c *ClientWithResponses) PersonalCalendarItemsV1ListWithResponse(ctx context.Context, params *PersonalCalendarItemsV1ListParams, reqEditors ...RequestEditorFn) (*PersonalCalendarItemsV1ListResponse, error) { + rsp, err := c.PersonalCalendarItemsV1List(ctx, params, reqEditors...) + if err != nil { + return nil, err + } + return ParsePersonalCalendarItemsV1ListResponse(rsp) +} + // RoomsV1ListWithResponse request returning *RoomsV1ListResponse func (c *ClientWithResponses) RoomsV1ListWithResponse(ctx context.Context, params *RoomsV1ListParams, reqEditors ...RequestEditorFn) (*RoomsV1ListResponse, error) { rsp, err := c.RoomsV1List(ctx, params, reqEditors...) @@ -3099,7 +3207,6 @@ func ParseFacultiesV1CreateResponse(rsp *http.Response) (*FacultiesV1CreateRespo switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201: var dest struct { - // Faculty 教員 Faculty Faculty `json:"faculty"` } if err := json.Unmarshal(bodyBytes, &dest); err != nil { @@ -3144,7 +3251,6 @@ func ParseFacultiesV1DetailResponse(rsp *http.Response) (*FacultiesV1DetailRespo switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: var dest struct { - // Faculty 教員 Faculty Faculty `json:"faculty"` } if err := json.Unmarshal(bodyBytes, &dest); err != nil { @@ -3173,7 +3279,6 @@ func ParseFacultiesV1UpdateResponse(rsp *http.Response) (*FacultiesV1UpdateRespo switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: var dest struct { - // Faculty 教員 Faculty Faculty `json:"faculty"` } if err := json.Unmarshal(bodyBytes, &dest); err != nil { @@ -3186,6 +3291,34 @@ func ParseFacultiesV1UpdateResponse(rsp *http.Response) (*FacultiesV1UpdateRespo return response, nil } +// ParsePersonalCalendarItemsV1ListResponse parses an HTTP response from a PersonalCalendarItemsV1ListWithResponse call +func ParsePersonalCalendarItemsV1ListResponse(rsp *http.Response) (*PersonalCalendarItemsV1ListResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &PersonalCalendarItemsV1ListResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest struct { + PersonalCalendarItems []PersonalCalendarItem `json:"personalCalendarItems"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + // ParseRoomsV1ListResponse parses an HTTP response from a RoomsV1ListWithResponse call func ParseRoomsV1ListResponse(rsp *http.Response) (*RoomsV1ListResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/internal/handler/handler_test.go b/internal/handler/handler_test.go new file mode 100644 index 0000000..6ff28e9 --- /dev/null +++ b/internal/handler/handler_test.go @@ -0,0 +1,148 @@ +package handler + +import ( + "encoding/json" + "net/http" + "net/http/httptest" + "net/url" + "testing" + "time" + + firebaseauth "firebase.google.com/go/v4/auth" + api "github.com/fun-dotto/admin-bff-api/generated" + "github.com/fun-dotto/admin-bff-api/generated/external/academic_api" + "github.com/fun-dotto/admin-bff-api/generated/external/announcement_api" + "github.com/fun-dotto/admin-bff-api/internal/middleware" + "github.com/gin-gonic/gin" +) + +func TestSubjectsV1List_UsesRenamedQueryParameters(t *testing.T) { + gin.SetMode(gin.TestMode) + + var gotQuery url.Values + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + gotQuery = r.URL.Query() + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"subjects":[]}`)) + })) + defer server.Close() + + h := newTestHandler(t, server.URL) + rec := httptest.NewRecorder() + c, _ := gin.CreateTestContext(rec) + c.Request = httptest.NewRequest(http.MethodGet, "/v1/subjects", nil) + setAdminClaim(c) + + q := "math" + year := 2026 + grades := []api.DottoFoundationV1Grade{api.B1} + courses := []api.DottoFoundationV1Course{api.InformationSystem} + classes := []api.DottoFoundationV1Class{api.A} + classifications := []api.DottoFoundationV1SubjectClassification{api.Cultural} + semesters := []api.DottoFoundationV1CourseSemester{api.Q1, api.Q2} + requirementTypes := []api.DottoFoundationV1SubjectRequirementType{api.Optional} + categories := []api.DottoFoundationV1CulturalSubjectCategory{api.Society} + + h.SubjectsV1List(c, api.SubjectsV1ListParams{ + Q: &q, + Grades: &grades, + Courses: &courses, + Classes: &classes, + Classifications: &classifications, + Year: &year, + Semesters: &semesters, + RequirementTypes: &requirementTypes, + CulturalSubjectCategories: &categories, + }) + + if rec.Code != http.StatusOK { + t.Fatalf("status = %d, want %d", rec.Code, http.StatusOK) + } + if gotQuery.Get("grades") == "" || gotQuery.Get("grade") != "" { + t.Fatalf("query grades = %q, grade = %q", gotQuery.Get("grades"), gotQuery.Get("grade")) + } + if gotQuery.Get("classes") == "" || gotQuery.Get("class") != "" { + t.Fatalf("query classes = %q, class = %q", gotQuery.Get("classes"), gotQuery.Get("class")) + } + if gotQuery.Get("classifications") == "" || gotQuery.Get("classification") != "" { + t.Fatalf("query classifications = %q, classification = %q", gotQuery.Get("classifications"), gotQuery.Get("classification")) + } + if gotQuery.Get("semesters") == "" || gotQuery.Get("semester") != "" { + t.Fatalf("query semesters = %q, semester = %q", gotQuery.Get("semesters"), gotQuery.Get("semester")) + } + if gotQuery.Get("requirementTypes") == "" || gotQuery.Get("requirementType") != "" { + t.Fatalf("query requirementTypes = %q, requirementType = %q", gotQuery.Get("requirementTypes"), gotQuery.Get("requirementType")) + } + if gotQuery.Get("culturalSubjectCategories") == "" || gotQuery.Get("culturalSubjectCategory") != "" { + t.Fatalf("query culturalSubjectCategories = %q, culturalSubjectCategory = %q", gotQuery.Get("culturalSubjectCategories"), gotQuery.Get("culturalSubjectCategory")) + } +} + +func TestPersonalCalendarItemsV1List_ProxiesAcademicAPI(t *testing.T) { + gin.SetMode(gin.TestMode) + + wantDate := time.Date(2026, 3, 26, 9, 0, 0, 0, time.UTC) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + query := r.URL.Query() + if got := query.Get("userId"); got != "user-1" { + t.Fatalf("userId = %q, want %q", got, "user-1") + } + if got := query.Get("dates"); got == "" { + t.Fatal("dates query parameter is empty") + } + + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(`{"personalCalendarItems":[{"date":"2026-03-26T09:00:00Z","slot":{"dayOfWeek":"Thursday","period":"first"},"timetableItem":{"id":"item-1","subject":{"id":"subject-1","name":"Algorithms"},"slot":{"dayOfWeek":"Thursday","period":"first"},"rooms":[]}}]}`)) + })) + defer server.Close() + + h := newTestHandler(t, server.URL) + rec := httptest.NewRecorder() + c, _ := gin.CreateTestContext(rec) + c.Request = httptest.NewRequest(http.MethodGet, "/v1/personalCalendarItems", nil) + setAdminClaim(c) + + h.PersonalCalendarItemsV1List(c, api.PersonalCalendarItemsV1ListParams{ + UserId: "user-1", + Dates: []time.Time{wantDate}, + }) + + if rec.Code != http.StatusOK { + t.Fatalf("status = %d, want %d", rec.Code, http.StatusOK) + } + + var body struct { + PersonalCalendarItems []struct { + Date string `json:"date"` + } `json:"personalCalendarItems"` + } + if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + t.Fatalf("unmarshal response: %v", err) + } + if len(body.PersonalCalendarItems) != 1 || body.PersonalCalendarItems[0].Date != "2026-03-26T09:00:00Z" { + t.Fatalf("unexpected response body: %s", rec.Body.String()) + } +} + +func newTestHandler(t *testing.T, baseURL string) *Handler { + t.Helper() + + academicClient, err := academic_api.NewClientWithResponses(baseURL) + if err != nil { + t.Fatalf("new academic client: %v", err) + } + announcementClient, err := announcement_api.NewClientWithResponses(baseURL) + if err != nil { + t.Fatalf("new announcement client: %v", err) + } + + return NewHandler(academicClient, announcementClient) +} + +func setAdminClaim(c *gin.Context) { + c.Set(middleware.FirebaseTokenContextKey, &firebaseauth.Token{ + Claims: map[string]interface{}{ + "admin": true, + }, + }) +} diff --git a/internal/handler/personal_calendar_item.go b/internal/handler/personal_calendar_item.go new file mode 100644 index 0000000..b2bbc5e --- /dev/null +++ b/internal/handler/personal_calendar_item.go @@ -0,0 +1,34 @@ +package handler + +import ( + "net/http" + + "github.com/gin-gonic/gin" + + api "github.com/fun-dotto/admin-bff-api/generated" + "github.com/fun-dotto/admin-bff-api/generated/external/academic_api" + "github.com/fun-dotto/admin-bff-api/internal/middleware" +) + +// PersonalCalendarItemsV1List 個人カレンダーアイテム一覧を取得する +func (h *Handler) PersonalCalendarItemsV1List(c *gin.Context, params api.PersonalCalendarItemsV1ListParams) { + if !middleware.RequireAnyClaim(c, "admin", "developer") { + return + } + + response, err := h.academicClient.PersonalCalendarItemsV1ListWithResponse(c.Request.Context(), &academic_api.PersonalCalendarItemsV1ListParams{ + UserId: params.UserId, + Dates: params.Dates, + }) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + if response.JSON200 == nil { + c.JSON(response.StatusCode(), gin.H{"error": "unexpected response from upstream"}) + return + } + + c.JSON(http.StatusOK, response.JSON200) +} diff --git a/internal/handler/subject.go b/internal/handler/subject.go index 3a54846..af57e02 100644 --- a/internal/handler/subject.go +++ b/internal/handler/subject.go @@ -17,15 +17,15 @@ func (h *Handler) SubjectsV1List(c *gin.Context, params api.SubjectsV1ListParams } clientParams := &academic_api.SubjectsV1ListParams{ - Q: params.Q, - Grade: convertSlicePtr[api.DottoFoundationV1Grade, academic_api.DottoFoundationV1Grade](params.Grade), - Courses: convertSlicePtr[api.DottoFoundationV1Course, academic_api.DottoFoundationV1Course](params.Courses), - Class: convertSlicePtr[api.DottoFoundationV1Class, academic_api.DottoFoundationV1Class](params.Class), - Classification: convertSlicePtr[api.DottoFoundationV1SubjectClassification, academic_api.DottoFoundationV1SubjectClassification](params.Classification), - Year: params.Year, - Semester: convertSlicePtr[api.DottoFoundationV1CourseSemester, academic_api.DottoFoundationV1CourseSemester](params.Semester), - RequirementType: convertSlicePtr[api.DottoFoundationV1SubjectRequirementType, academic_api.DottoFoundationV1SubjectRequirementType](params.RequirementType), - CulturalSubjectCategory: convertSlicePtr[api.DottoFoundationV1CulturalSubjectCategory, academic_api.DottoFoundationV1CulturalSubjectCategory](params.CulturalSubjectCategory), + Q: params.Q, + Grades: convertSlicePtr[api.DottoFoundationV1Grade, academic_api.DottoFoundationV1Grade](params.Grades), + Courses: convertSlicePtr[api.DottoFoundationV1Course, academic_api.DottoFoundationV1Course](params.Courses), + Classes: convertSlicePtr[api.DottoFoundationV1Class, academic_api.DottoFoundationV1Class](params.Classes), + Classifications: convertSlicePtr[api.DottoFoundationV1SubjectClassification, academic_api.DottoFoundationV1SubjectClassification](params.Classifications), + Year: params.Year, + Semesters: convertSlicePtr[api.DottoFoundationV1CourseSemester, academic_api.DottoFoundationV1CourseSemester](params.Semesters), + RequirementTypes: convertSlicePtr[api.DottoFoundationV1SubjectRequirementType, academic_api.DottoFoundationV1SubjectRequirementType](params.RequirementTypes), + CulturalSubjectCategories: convertSlicePtr[api.DottoFoundationV1CulturalSubjectCategory, academic_api.DottoFoundationV1CulturalSubjectCategory](params.CulturalSubjectCategories), } response, err := h.academicClient.SubjectsV1ListWithResponse(c.Request.Context(), clientParams) diff --git a/openapi/external/academic_api/openapi.yaml b/openapi/external/academic_api/openapi.yaml index 18a2a1b..e13f6f6 100644 --- a/openapi/external/academic_api/openapi.yaml +++ b/openapi/external/academic_api/openapi.yaml @@ -3,13 +3,14 @@ info: title: Academic Service version: 1.0.0 tags: - - name: Subjects - - name: Syllabus - - name: Faculties - name: CourseRegistrations - - name: TimetableItems + - name: Faculties + - name: PersonalCalendarItems - name: Rooms - name: Reservations + - name: Subjects + - name: Syllabus + - name: TimetableItems paths: /v1/courseRegistrations: get: @@ -30,12 +31,14 @@ paths: schema: type: integer explode: false - - name: semester + - name: semesters in: query required: true - description: 開講時期 + description: 開講時期; 指定された時期に開講される全ての科目が取得される schema: - $ref: '#/components/schemas/DottoFoundationV1.CourseSemester' + type: array + items: + $ref: '#/components/schemas/DottoFoundationV1.CourseSemester' explode: false responses: '200': @@ -232,6 +235,44 @@ paths: description: The server cannot find the requested resource. tags: - Faculties + /v1/personalCalendarItems: + get: + operationId: PersonalCalendarItemsV1_list + description: 個人カレンダーアイテム一覧を取得する + parameters: + - name: userId + in: query + required: true + description: ユーザーID + schema: + type: string + explode: false + - name: dates + in: query + required: true + description: 日付のリスト; 指定した日付の個人カレンダーアイテムのみを取得する + schema: + type: array + items: + type: string + format: date-time + explode: false + responses: + '200': + description: 個人カレンダーアイテムのリスト; 時間割、履修情報、休講補講、振替授業日情報から構築される + content: + application/json: + schema: + type: object + properties: + personalCalendarItems: + type: array + items: + $ref: '#/components/schemas/PersonalCalendarItem' + required: + - personalCalendarItems + tags: + - PersonalCalendarItems /v1/rooms: get: operationId: RoomsV1_list @@ -440,7 +481,7 @@ paths: schema: type: string explode: false - - name: grade + - name: grades in: query required: false description: 学年 @@ -458,7 +499,7 @@ paths: items: $ref: '#/components/schemas/DottoFoundationV1.Course' explode: false - - name: class + - name: classes in: query required: false description: クラス; 大学院の学年を選択した場合は選択できない @@ -467,7 +508,7 @@ paths: items: $ref: '#/components/schemas/DottoFoundationV1.Class' explode: false - - name: classification + - name: classifications in: query required: false description: '学部: 専門・教養; 大学院: 専門・研究指導' @@ -483,7 +524,7 @@ paths: schema: type: integer explode: false - - name: semester + - name: semesters in: query required: false description: 開講時期 @@ -492,7 +533,7 @@ paths: items: $ref: '#/components/schemas/DottoFoundationV1.CourseSemester' explode: false - - name: requirementType + - name: requirementTypes in: query required: false description: 必修・選択・選択必修 @@ -501,7 +542,7 @@ paths: items: $ref: '#/components/schemas/DottoFoundationV1.SubjectRequirementType' explode: false - - name: culturalSubjectCategory + - name: culturalSubjectCategories in: query required: false description: 教養科目カテゴリ @@ -636,21 +677,14 @@ paths: schema: type: integer explode: false - - name: semester + - name: semesters in: query required: true - description: 開講時期 - schema: - $ref: '#/components/schemas/DottoFoundationV1.CourseSemester' - explode: false - - name: dayOfWeek - in: query - required: false - description: 曜日; 複数指定時はORでフィルタリングされる; 指定しない場合は全ての曜日が選択される + description: 開講時期; 指定された時期に開講される全ての科目が取得される schema: type: array items: - $ref: '#/components/schemas/DottoFoundationV1.DayOfWeek' + $ref: '#/components/schemas/DottoFoundationV1.CourseSemester' explode: false responses: '200': @@ -839,6 +873,16 @@ components: - Optional - OptionalRequired description: 必修・選択 + DottoFoundationV1.TimetableSlot: + type: object + required: + - dayOfWeek + - period + properties: + dayOfWeek: + $ref: '#/components/schemas/DottoFoundationV1.DayOfWeek' + period: + $ref: '#/components/schemas/DottoFoundationV1.Period' Faculty: type: object required: @@ -852,7 +896,6 @@ components: type: string email: type: string - description: 教員 FacultyRequest: type: object required: @@ -863,6 +906,34 @@ components: type: string email: type: string + PersonalCalendarItem: + type: object + required: + - date + - slot + - timetableItem + properties: + date: + type: string + format: date-time + slot: + $ref: '#/components/schemas/DottoFoundationV1.TimetableSlot' + timetableItem: + $ref: '#/components/schemas/TimetableItem' + PersonalCalendarItemRequest: + type: object + required: + - date + - slot + - timetableItemId + properties: + date: + type: string + format: date-time + slot: + $ref: '#/components/schemas/DottoFoundationV1.TimetableSlot' + timetableItemId: + type: string Reservation: type: object required: @@ -1132,30 +1203,29 @@ components: required: - id - subject - - dayOfWeek - - period + - rooms properties: id: type: string subject: $ref: '#/components/schemas/SubjectSummary' - dayOfWeek: - $ref: '#/components/schemas/DottoFoundationV1.DayOfWeek' - period: - $ref: '#/components/schemas/DottoFoundationV1.Period' + slot: + allOf: + - $ref: '#/components/schemas/DottoFoundationV1.TimetableSlot' + description: 集中講義など、時間割に含まれていない場合はnull + rooms: + type: array + items: + $ref: '#/components/schemas/Room' TimetableItemRequest: type: object required: - subjectId - - dayOfWeek - - period properties: subjectId: type: string - dayOfWeek: - $ref: '#/components/schemas/DottoFoundationV1.DayOfWeek' - period: - $ref: '#/components/schemas/DottoFoundationV1.Period' + slot: + $ref: '#/components/schemas/DottoFoundationV1.TimetableSlot' servers: - url: http://localhost:8080 description: Local diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 5868297..4b7b8d5 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -5,9 +5,10 @@ info: tags: - name: Announcements - name: CourseRegistrations + - name: Faculties + - name: PersonalCalendarItems - name: Rooms - name: Reservations - - name: Faculties - name: Subjects - name: TimetableItems - name: Users @@ -163,12 +164,14 @@ paths: schema: type: integer explode: false - - name: semester + - name: semesters in: query required: true description: 開講時期 schema: - $ref: '#/components/schemas/DottoFoundationV1.CourseSemester' + type: array + items: + $ref: '#/components/schemas/DottoFoundationV1.CourseSemester' explode: false responses: '200': @@ -368,6 +371,44 @@ paths: description: The server cannot find the requested resource. tags: - Faculties + /v1/personalCalendarItems: + get: + operationId: PersonalCalendarItemsV1_list + description: 個人カレンダーアイテム一覧を取得する + parameters: + - name: userId + in: query + required: true + description: ユーザーID + schema: + type: string + explode: false + - name: dates + in: query + required: true + description: 日付のリスト; 指定した日付の個人カレンダーアイテムのみを取得する + schema: + type: array + items: + type: string + format: date-time + explode: false + responses: + '200': + description: 個人カレンダーアイテムのリスト; 時間割、履修情報、休講補講、振替授業日情報から構築される + content: + application/json: + schema: + type: object + properties: + personalCalendarItems: + type: array + items: + $ref: '#/components/schemas/AcademicService.PersonalCalendarItem' + required: + - personalCalendarItems + tags: + - PersonalCalendarItems /v1/rooms: get: operationId: RoomsV1_list @@ -569,7 +610,7 @@ paths: schema: type: string explode: false - - name: grade + - name: grades in: query required: false description: 学年 @@ -587,7 +628,7 @@ paths: items: $ref: '#/components/schemas/DottoFoundationV1.Course' explode: false - - name: class + - name: classes in: query required: false description: クラス; 大学院の学年を選択した場合は選択できない @@ -596,7 +637,7 @@ paths: items: $ref: '#/components/schemas/DottoFoundationV1.Class' explode: false - - name: classification + - name: classifications in: query required: false description: '学部: 専門・教養; 大学院: 専門・研究指導' @@ -612,7 +653,7 @@ paths: schema: type: integer explode: false - - name: semester + - name: semesters in: query required: false description: 開講時期 @@ -621,7 +662,7 @@ paths: items: $ref: '#/components/schemas/DottoFoundationV1.CourseSemester' explode: false - - name: requirementType + - name: requirementTypes in: query required: false description: 必修・選択・選択必修 @@ -630,7 +671,7 @@ paths: items: $ref: '#/components/schemas/DottoFoundationV1.SubjectRequirementType' explode: false - - name: culturalSubjectCategory + - name: culturalSubjectCategories in: query required: false description: 教養科目カテゴリ @@ -744,12 +785,14 @@ paths: schema: type: integer explode: false - - name: semester + - name: semesters in: query required: true description: 開講時期 schema: - $ref: '#/components/schemas/DottoFoundationV1.CourseSemester' + type: array + items: + $ref: '#/components/schemas/DottoFoundationV1.CourseSemester' explode: false - name: dayOfWeek in: query @@ -894,7 +937,6 @@ components: type: string email: type: string - description: 教員 AcademicService.FacultyRequest: type: object required: @@ -905,6 +947,20 @@ components: type: string email: type: string + AcademicService.PersonalCalendarItem: + type: object + required: + - date + - slot + - timetableItem + properties: + date: + type: string + format: date-time + slot: + $ref: '#/components/schemas/DottoFoundationV1.TimetableSlot' + timetableItem: + $ref: '#/components/schemas/AcademicService.TimetableItem' AcademicService.Reservation: type: object required: @@ -1042,30 +1098,29 @@ components: required: - id - subject - - dayOfWeek - - period + - rooms properties: id: type: string subject: $ref: '#/components/schemas/AcademicService.SubjectSummary' - dayOfWeek: - $ref: '#/components/schemas/DottoFoundationV1.DayOfWeek' - period: - $ref: '#/components/schemas/DottoFoundationV1.Period' + slot: + allOf: + - $ref: '#/components/schemas/DottoFoundationV1.TimetableSlot' + description: 集中講義など、時間割に含まれていない場合はnull + rooms: + type: array + items: + $ref: '#/components/schemas/AcademicService.Room' AcademicService.TimetableItemRequest: type: object required: - subjectId - - dayOfWeek - - period properties: subjectId: type: string - dayOfWeek: - $ref: '#/components/schemas/DottoFoundationV1.DayOfWeek' - period: - $ref: '#/components/schemas/DottoFoundationV1.Period' + slot: + $ref: '#/components/schemas/DottoFoundationV1.TimetableSlot' AnnouncementService.Announcement: type: object required: @@ -1208,6 +1263,16 @@ components: - Optional - OptionalRequired description: 必修・選択 + DottoFoundationV1.TimetableSlot: + type: object + required: + - dayOfWeek + - period + properties: + dayOfWeek: + $ref: '#/components/schemas/DottoFoundationV1.DayOfWeek' + period: + $ref: '#/components/schemas/DottoFoundationV1.Period' UserService.User: type: object required: