66import com .leets7th .job_is_be .domain .job .repository .RegionRepository ;
77import com .leets7th .job_is_be .domain .user .dto .ProfileDraftRequest ;
88import com .leets7th .job_is_be .domain .user .dto .ProfileDraftResponse ;
9+ import com .leets7th .job_is_be .domain .user .dto .ProfileJobCategoryResponse ;
10+ import com .leets7th .job_is_be .domain .user .dto .ProfileRegionResponse ;
11+ import com .leets7th .job_is_be .domain .user .dto .ProfileResponse ;
12+ import com .leets7th .job_is_be .domain .user .dto .ProfileUpdateRequest ;
913import com .leets7th .job_is_be .domain .user .entity .User ;
1014import com .leets7th .job_is_be .domain .user .entity .UserJobCategory ;
1115import com .leets7th .job_is_be .domain .user .entity .UserProfile ;
@@ -132,6 +136,68 @@ public void completeOnboarding(Long userId) {
132136 profile .completeOnboarding (LocalDateTime .now ());
133137 }
134138
139+ @ Transactional (readOnly = true )
140+ public ProfileResponse getProfile (Long userId ) {
141+ UserProfile profile = findCompletedProfile (userId );
142+ return toProfileResponse (profile , findJobCategories (userId ), findRegion (userId ));
143+ }
144+
145+ @ Transactional
146+ public ProfileResponse updateProfile (Long userId , ProfileUpdateRequest request ) {
147+ UserProfile profile = findCompletedProfile (userId );
148+ if (request == null ) {
149+ return toProfileResponse (profile , findJobCategories (userId ), findRegion (userId ));
150+ }
151+
152+ User user = profile .getUser ();
153+ List <UserJobCategory > currentSelections = findJobCategories (userId );
154+ UserRegion currentRegion = findRegion (userId );
155+
156+ if (request .jobCategoryIds () != null || request .primaryJobCategoryId () != null ) {
157+ List <Long > categoryIds = request .jobCategoryIds () != null
158+ ? request .jobCategoryIds ()
159+ : currentSelections .stream ()
160+ .map (selection -> selection .getJobCategory ().getId ())
161+ .toList ();
162+ Long primaryId = request .primaryJobCategoryId () != null
163+ ? request .primaryJobCategoryId ()
164+ : currentSelections .stream ()
165+ .filter (UserJobCategory ::isPrimary )
166+ .map (selection -> selection .getJobCategory ().getId ())
167+ .findFirst ()
168+ .orElse (null );
169+ List <JobCategory > categories = resolveJobCategories (categoryIds , primaryId );
170+ if (categories .isEmpty ()) {
171+ throw new GeneralException (ErrorStatus .PROFILE_REQUIRED_FIELDS_MISSING );
172+ }
173+ replaceJobCategories (user , categories , primaryId );
174+ }
175+
176+ if (request .regionId () != null ) {
177+ replaceRegion (user , resolveRegion (request .regionId ()));
178+ }
179+
180+ profile .updateProfile (
181+ request .careerLevel () != null ? request .careerLevel () : profile .getCareerLevel (),
182+ request .preferenceNotes () != null
183+ ? valueCodec .encode (request .preferenceNotes ())
184+ : profile .getPreferenceNote (),
185+ request .excludeKeywords () != null
186+ ? valueCodec .encode (request .excludeKeywords ())
187+ : profile .getExcludeKeywords (),
188+ request .techStacks () != null
189+ ? valueCodec .encode (request .techStacks ())
190+ : profile .getTechStack ()
191+ );
192+
193+ List <UserJobCategory > updatedSelections = findJobCategories (userId );
194+ UserRegion updatedRegion = findRegion (userId );
195+ if (updatedSelections .isEmpty () || updatedRegion == null || profile .getCareerLevel () == null ) {
196+ throw new GeneralException (ErrorStatus .PROFILE_REQUIRED_FIELDS_MISSING );
197+ }
198+ return toProfileResponse (profile , updatedSelections , updatedRegion );
199+ }
200+
135201 private List <JobCategory > resolveJobCategories (List <Long > requestedIds , Long primaryId ) {
136202 List <Long > ids = requestedIds == null ? List .of () : requestedIds ;
137203 LinkedHashSet <Long > uniqueIds = new LinkedHashSet <>(ids );
@@ -209,16 +275,16 @@ private ProfileDraftResponse toDraftResponse(
209275 return left .getJobCategory ().getId ().compareTo (right .getJobCategory ().getId ());
210276 });
211277
212- List <ProfileDraftResponse . JobCategoryItem > jobCategories = orderedSelections .stream ()
213- .map (selection -> new ProfileDraftResponse . JobCategoryItem (
278+ List <ProfileJobCategoryResponse > jobCategories = orderedSelections .stream ()
279+ .map (selection -> new ProfileJobCategoryResponse (
214280 selection .getJobCategory ().getId (),
215281 selection .getJobCategory ().getName (),
216282 selection .isPrimary ()
217283 ))
218284 .toList ();
219- ProfileDraftResponse . RegionItem region = userRegion == null
285+ ProfileRegionResponse region = userRegion == null
220286 ? null
221- : new ProfileDraftResponse . RegionItem (
287+ : new ProfileRegionResponse (
222288 userRegion .getRegion ().getId (),
223289 userRegion .getRegion ().getName ()
224290 );
@@ -234,4 +300,49 @@ private ProfileDraftResponse toDraftResponse(
234300 profile .isJobTestCompleted ()
235301 );
236302 }
303+
304+ private UserProfile findCompletedProfile (Long userId ) {
305+ UserProfile profile = userProfileRepository .findByUserId (userId )
306+ .orElseThrow (() -> new GeneralException (ErrorStatus .PROFILE_NOT_FOUND ));
307+ if (!profile .isOnboardingCompleted ()) {
308+ throw new GeneralException (ErrorStatus .PROFILE_NOT_FOUND );
309+ }
310+ return profile ;
311+ }
312+
313+ private ProfileResponse toProfileResponse (
314+ UserProfile profile ,
315+ List <UserJobCategory > selections ,
316+ UserRegion userRegion
317+ ) {
318+ List <ProfileJobCategoryResponse > jobCategories = selections .stream ()
319+ .sorted ((left , right ) -> {
320+ if (left .isPrimary () != right .isPrimary ()) {
321+ return left .isPrimary () ? -1 : 1 ;
322+ }
323+ return left .getJobCategory ().getId ().compareTo (right .getJobCategory ().getId ());
324+ })
325+ .map (selection -> new ProfileJobCategoryResponse (
326+ selection .getJobCategory ().getId (),
327+ selection .getJobCategory ().getName (),
328+ selection .isPrimary ()
329+ ))
330+ .toList ();
331+ ProfileRegionResponse region = new ProfileRegionResponse (
332+ userRegion .getRegion ().getId (),
333+ userRegion .getRegion ().getName ()
334+ );
335+ return new ProfileResponse (
336+ profile .getUser ().getId (),
337+ jobCategories ,
338+ region ,
339+ profile .getCareerLevel (),
340+ valueCodec .decode (profile .getPreferenceNote ()),
341+ valueCodec .decode (profile .getExcludeKeywords ()),
342+ valueCodec .decode (profile .getTechStack ()),
343+ profile .isJobTestCompleted (),
344+ profile .isOnboardingCompleted (),
345+ profile .getOnboardingCompletedAt ()
346+ );
347+ }
237348}
0 commit comments