Line data Source code
1 : // Package controller は 学歴に関するエンドポイントを提供します。
2 : package controller
3 :
4 : import (
5 : "errors"
6 : "net/http"
7 : "strconv"
8 :
9 : "github.com/gin-gonic/gin"
10 : "github.com/go-playground/validator/v10"
11 :
12 : "resume/internal/adapter/http/dto/request"
13 : "resume/internal/adapter/http/handlerutil"
14 : "resume/internal/shared/apperr"
15 : "resume/internal/shared/ctx/auth"
16 : "resume/internal/shared/util"
17 : uceducation "resume/internal/usecase/education"
18 : )
19 :
20 : // EducationHandler は 学歴 を提供するHTTPエンドポイントのハンドラです
21 : type EducationHandler struct {
22 : uc uceducation.Usecase
23 : }
24 :
25 : // NewEducationHandler は 学歴ユースケースを注入した新しい EducationHandler を生成します
26 : func NewEducationHandler(
27 : uc uceducation.Usecase,
28 0 : ) *EducationHandler {
29 0 : return &EducationHandler{
30 0 : uc: uc,
31 0 : }
32 0 : }
33 :
34 : // ListEducation は 現在ログイン中のユーザーに紐づく学歴一覧を取得します。
35 0 : func (h *EducationHandler) ListEducation(c *gin.Context) {
36 0 : userID, ok := auth.UserID(c)
37 0 : if !ok || userID == 0 {
38 0 : handlerutil.WriteError(
39 0 : c,
40 0 : apperr.New(apperr.CodeUnauthorized, "unauthorized", nil),
41 0 : )
42 0 : return
43 0 : }
44 0 : in := uceducation.ListInput{
45 0 : UserID: userID,
46 0 : }
47 0 : out, err := h.uc.ListUserEducation(c.Request.Context(), in)
48 0 : if err != nil {
49 0 : handlerutil.WriteError(c, err)
50 0 : return
51 0 : }
52 0 : c.JSON(http.StatusOK, out)
53 : }
54 :
55 : // AddEducation は 認証済みユーザーが 学歴情報 を登録する
56 0 : func (h *EducationHandler) AddEducation(c *gin.Context) {
57 0 : _, ok := auth.From(c.Request.Context())
58 0 : if !ok {
59 0 : handlerutil.WriteError(
60 0 : c,
61 0 : apperr.New(apperr.CodeUnauthorized, "unauthorized", nil),
62 0 : )
63 0 : return
64 0 : }
65 0 : var req request.AddEducationRequest
66 0 : if err := c.ShouldBindJSON(&req); err != nil {
67 0 : var verrs validator.ValidationErrors
68 0 : if errors.As(err, &verrs) {
69 0 : env := handlerutil.BuildValidationEnvelope(c, verrs, "domain.userEducation")
70 0 : handlerutil.WriteValidationError(c, env)
71 0 : return
72 0 : }
73 0 : handlerutil.WriteError(c, err)
74 0 : return
75 : }
76 0 : userID, ok := auth.UserID(c)
77 0 : if !ok || userID == 0 {
78 0 : handlerutil.WriteError(
79 0 : c,
80 0 : apperr.New(apperr.CodeUnauthorized, "unauthorized", nil),
81 0 : )
82 0 : return
83 0 : }
84 0 : eventDate, err := util.ParseYearMonthVal(req.EventDate)
85 0 : if err != nil {
86 0 : handlerutil.WriteError(c, apperr.New(apperr.CodeBadRequest, "invalid enrollment date", nil))
87 0 : }
88 0 : in := uceducation.CreateInput{
89 0 : UserID: userID,
90 0 : InstitutionName: req.InstitutionName,
91 0 : FacultyName: req.FacultyName,
92 0 : DepartmentName: req.DepartmentName,
93 0 : DegreeTypeID: req.DegreeTypeID,
94 0 : EducationStatusID: req.EducationStatusID,
95 0 : EventDate: eventDate,
96 0 : Description: req.Description,
97 0 : IsPublic: req.IsPublic,
98 0 : }
99 0 : out, err := h.uc.CreateUserEducation(c.Request.Context(), in)
100 0 : if err != nil {
101 0 : handlerutil.WriteError(c, err)
102 0 : return
103 0 : }
104 0 : c.JSON(http.StatusCreated, out)
105 : }
106 :
107 : // UpdateEducation は 認証済みユーザーが 学歴情報 を更新する
108 0 : func (h *EducationHandler) UpdateEducation(c *gin.Context) {
109 0 : _, ok := auth.From(c.Request.Context())
110 0 : if !ok {
111 0 : handlerutil.WriteError(
112 0 : c,
113 0 : apperr.New(apperr.CodeUnauthorized, "unauthorized", nil),
114 0 : )
115 0 : return
116 0 : }
117 0 : var req request.UpdateEducationRequest
118 0 : if err := c.ShouldBindJSON(&req); err != nil {
119 0 : var verrs validator.ValidationErrors
120 0 : if errors.As(err, &verrs) {
121 0 : env := handlerutil.BuildValidationEnvelope(c, verrs, "domain.userEducation")
122 0 : handlerutil.WriteValidationError(c, env)
123 0 : return
124 0 : }
125 0 : handlerutil.WriteError(c, err)
126 0 : return
127 : }
128 0 : userID, ok := auth.UserID(c)
129 0 : if !ok || userID == 0 {
130 0 : handlerutil.WriteError(
131 0 : c,
132 0 : apperr.New(apperr.CodeUnauthorized, "unauthorized", nil),
133 0 : )
134 0 : return
135 0 : }
136 0 : educationIDStr := c.Param("education_id")
137 0 : educationID, err := strconv.ParseUint(educationIDStr, 10, 64)
138 0 : if err != nil {
139 0 : c.JSON(http.StatusBadRequest, gin.H{
140 0 : "error": "invalid education_id",
141 0 : })
142 0 : return
143 0 : }
144 0 : eventDate, err := util.ParseYearMonthVal(req.EventDate)
145 0 : if err != nil {
146 0 : handlerutil.WriteError(c, apperr.New(apperr.CodeBadRequest, "invalid enrollment date", nil))
147 0 : }
148 0 : in := uceducation.UpdateInput{
149 0 : EducationID: educationID,
150 0 : UserID: userID,
151 0 : InstitutionName: req.InstitutionName,
152 0 : FacultyName: req.FacultyName,
153 0 : DepartmentName: req.DepartmentName,
154 0 : DegreeTypeID: req.DegreeTypeID,
155 0 : EducationStatusID: req.EducationStatusID,
156 0 : EventDate: eventDate,
157 0 : Description: req.Description,
158 0 : IsPublic: req.IsPublic,
159 0 : }
160 0 : out, err := h.uc.UpdateUserEducation(c.Request.Context(), in)
161 0 : if err != nil {
162 0 : handlerutil.WriteError(c, err)
163 0 : return
164 0 : }
165 0 : c.JSON(http.StatusOK, out)
166 : }
167 :
168 : // DeleteEducation は 認証済みユーザーが 学歴情報 を削除する
169 : // 削除後 他の学歴で並び順を変更する
170 0 : func (h *EducationHandler) DeleteEducation(c *gin.Context) {
171 0 : educationIDStr := c.Param("education_id")
172 0 : educationID, err := strconv.ParseUint(educationIDStr, 10, 64)
173 0 : if err != nil {
174 0 : c.JSON(http.StatusBadRequest, gin.H{
175 0 : "error": "invalid education_id",
176 0 : })
177 0 : return
178 0 : }
179 0 : userID, ok := auth.UserID(c)
180 0 : if !ok || userID == 0 {
181 0 : handlerutil.WriteError(c, apperr.New(apperr.CodeUnauthorized, "unauthorized", nil))
182 0 : return
183 0 : }
184 0 : in := uceducation.DeleteInput{EducationID: educationID, UserID: userID}
185 0 : _, err = h.uc.DeleteUserEducation(c.Request.Context(), in)
186 0 : if err != nil {
187 0 : handlerutil.WriteError(c, err)
188 0 : return
189 0 : }
190 0 : c.Status(http.StatusNoContent)
191 : }
192 :
193 : // OrderEducation は 認証済みユーザーが 学歴情報 の 並び順を変更 する
194 0 : func (h *EducationHandler) OrderEducation(c *gin.Context) {
195 0 : _, ok := auth.From(c.Request.Context())
196 0 : if !ok {
197 0 : handlerutil.WriteError(
198 0 : c,
199 0 : apperr.New(apperr.CodeUnauthorized, "unauthorized", nil),
200 0 : )
201 0 : return
202 0 : }
203 0 : var req request.OrderEducationRequest
204 0 : if err := c.ShouldBindJSON(&req); err != nil {
205 0 : var verrs validator.ValidationErrors
206 0 : if errors.As(err, &verrs) {
207 0 : env := handlerutil.BuildValidationEnvelope(c, verrs, "domain.userEducation")
208 0 : handlerutil.WriteValidationError(c, env)
209 0 : return
210 0 : }
211 0 : handlerutil.WriteError(c, err)
212 0 : return
213 : }
214 0 : userID, ok := auth.UserID(c)
215 0 : if !ok || userID == 0 {
216 0 : handlerutil.WriteError(
217 0 : c,
218 0 : apperr.New(apperr.CodeUnauthorized, "unauthorized", nil),
219 0 : )
220 0 : return
221 0 : }
222 0 : in := uceducation.ReorderInput{
223 0 : UserID: userID,
224 0 : EducationIDs: req.EducationIDs,
225 0 : }
226 0 : _, err := h.uc.ReorderEducation(c.Request.Context(), in)
227 0 : if err != nil {
228 0 : handlerutil.WriteError(c, err)
229 0 : return
230 0 : }
231 0 : c.Status(http.StatusNoContent)
232 : }
233 :
234 : // ExistsEducation は 認証済みユーザーが 学歴情報 の 有無を返す
235 0 : func (h *EducationHandler) ExistsEducation(c *gin.Context) {
236 0 : userID, ok := auth.UserID(c)
237 0 : if !ok || userID == 0 {
238 0 : handlerutil.WriteError(c, apperr.New(apperr.CodeUnauthorized, "unauthorized", nil))
239 0 : return
240 0 : }
241 0 : in := uceducation.HasEducationInput{
242 0 : UserID: userID,
243 0 : }
244 0 : out, err := h.uc.HasUserEducation(c.Request.Context(), in)
245 0 : if err != nil {
246 0 : handlerutil.WriteError(c, err)
247 0 : return
248 0 : }
249 0 : c.JSON(http.StatusOK, out)
250 : }
|