Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.jobdri.jobdri_api.domain.mockapply.dto.request.MockApplyCreateMockFromJobPostingRequest;
import com.jobdri.jobdri_api.domain.mockapply.dto.request.MockApplyCreateMockRequest;
import com.jobdri.jobdri_api.domain.mockapply.dto.response.MockApplyCreateResponse;
import com.jobdri.jobdri_api.domain.mockapply.dto.response.MockApplySequenceResponse;
import com.jobdri.jobdri_api.domain.jobposting.dto.response.JobPostingResponse;
import com.jobdri.jobdri_api.domain.mockapply.service.MockApplyService;
import com.jobdri.jobdri_api.global.apiPayload.ApiResponse;
Expand Down Expand Up @@ -191,4 +192,19 @@ public ApiResponse<JobPostingResponse> getMockApplyJobPosting(
mockApplyService.getMockApplyJobPosting(userDetails.getUser(), mockApplyId)
);
}

@Operation(
summary = "같은 공고 기준 자소서 개수 및 순번 조회",
description = "현재 mockApply가 연결된 채용 공고 기준으로, 로그인 사용자가 생성한 자소서 총 개수와 현재 자소서 순번을 조회합니다."
)
@GetMapping("/{mockApplyId}/sequence")
public ApiResponse<MockApplySequenceResponse> getMockApplySequence(
@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable Long mockApplyId
) {
return ApiResponse.onSuccess(
"자소서 순번 조회에 성공했습니다.",
mockApplyService.getMockApplySequence(userDetails.getUser(), mockApplyId)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.jobdri.jobdri_api.domain.mockapply.dto.response;

public record MockApplySequenceResponse(
Long jobPostingId,
Long mockApplyId,
int totalCount,
int sequence
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@

import com.jobdri.jobdri_api.domain.mockapply.entity.MockApply;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface MockApplyRepository extends JpaRepository<MockApply, Long> {
List<MockApply> findAllByUserId(Long userId);
List<MockApply> findAllByJobPostingId(Long jobPostingId);
long countByUserIdAndJobPostingId(Long userId, Long jobPostingId);

@Query("""
select count(ma)
from MockApply ma
where ma.user.id = :userId
and ma.jobPosting.id = :jobPostingId
and (
ma.createdAt < :createdAt
or (ma.createdAt = :createdAt and ma.id <= :mockApplyId)
)
""")
long countSequenceByUserIdAndJobPostingId(
@Param("userId") Long userId,
@Param("jobPostingId") Long jobPostingId,
@Param("createdAt") java.time.LocalDateTime createdAt,
@Param("mockApplyId") Long mockApplyId
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.jobdri.jobdri_api.domain.mockapply.dto.request.MockApplyCreateMockFromJobPostingRequest;
import com.jobdri.jobdri_api.domain.mockapply.dto.request.MockApplyCreateMockRequest;
import com.jobdri.jobdri_api.domain.mockapply.dto.response.MockApplyCreateResponse;
import com.jobdri.jobdri_api.domain.mockapply.dto.response.MockApplySequenceResponse;
import com.jobdri.jobdri_api.domain.mockapply.entity.ApplyType;
import com.jobdri.jobdri_api.domain.mockapply.entity.MockApply;
import com.jobdri.jobdri_api.domain.mockapply.repository.MockApplyRepository;
Expand Down Expand Up @@ -89,6 +90,38 @@ public JobPostingResponse getMockApplyJobPosting(User user, Long mockApplyId) {
return JobPostingResponse.from(mockApply.getJobPosting());
}

public MockApplySequenceResponse getMockApplySequence(User user, Long mockApplyId) {
User validatedUser = userService.validateUser(user);
MockApply mockApply = getOwnedMockApply(validatedUser, mockApplyId);
Long jobPostingId = mockApply.getJobPosting().getId();

int totalCount = Math.toIntExact(
mockApplyRepository.countByUserIdAndJobPostingId(validatedUser.getId(), jobPostingId)
);
int sequence = Math.toIntExact(
mockApplyRepository.countSequenceByUserIdAndJobPostingId(
validatedUser.getId(),
jobPostingId,
mockApply.getCreatedAt(),
mockApply.getId()
)
);

if (sequence < 1 || sequence > totalCount) {
throw new GeneralException(
GeneralErrorCode.MOCK_APPLY_NOT_FOUND,
"해당 공고에 연결된 모의 서류 지원 순서를 찾을 수 없습니다. mockApplyId=" + mockApplyId
);
}

return new MockApplySequenceResponse(
jobPostingId,
mockApply.getId(),
totalCount,
sequence
);
}

private MockApply getOwnedMockApply(User user, Long mockApplyId) {
MockApply mockApply = mockApplyRepository.findById(mockApplyId)
.orElseThrow(() -> new GeneralException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.jobdri.jobdri_api.domain.jobposting.service.MockJobPostingGenerationService;
import com.jobdri.jobdri_api.domain.mockapply.dto.request.MockApplyCreateMockRequest;
import com.jobdri.jobdri_api.domain.mockapply.dto.response.MockApplyCreateResponse;
import com.jobdri.jobdri_api.domain.mockapply.dto.response.MockApplySequenceResponse;
import com.jobdri.jobdri_api.domain.mockapply.entity.ApplyType;
import com.jobdri.jobdri_api.domain.mockapply.entity.MockApply;
import com.jobdri.jobdri_api.domain.mockapply.entity.MockApplyStatus;
Expand All @@ -28,8 +29,10 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -152,6 +155,31 @@ void getMockApplyJobPosting() {
assertThat(response.getCompanyName()).isEqualTo(jobPosting.getCompany().getName());
}

@Test
@DisplayName("같은 공고 기준 자소서 총 개수와 현재 순번을 조회한다")
void getMockApplySequence() {
User user = saveUser("sequence@example.com");
JobPosting jobPosting = saveJobPosting(user, "백엔드 개발");
MockApply first = mockApplyRepository.save(MockApply.create(user, jobPosting, ApplyType.MOCK));
MockApply second = mockApplyRepository.save(MockApply.create(user, jobPosting, ApplyType.MOCK));
MockApply third = mockApplyRepository.save(MockApply.create(user, jobPosting, ApplyType.ACTUAL));

LocalDateTime baseTime = LocalDateTime.of(2026, 1, 1, 12, 0);
ReflectionTestUtils.setField(first, "createdAt", baseTime);
ReflectionTestUtils.setField(second, "createdAt", baseTime.plusMinutes(1));
ReflectionTestUtils.setField(third, "createdAt", baseTime.plusMinutes(2));
mockApplyRepository.saveAndFlush(first);
mockApplyRepository.saveAndFlush(second);
mockApplyRepository.saveAndFlush(third);

MockApplySequenceResponse response = mockApplyService.getMockApplySequence(user, second.getId());

assertThat(response.jobPostingId()).isEqualTo(jobPosting.getId());
assertThat(response.mockApplyId()).isEqualTo(second.getId());
assertThat(response.totalCount()).isEqualTo(3);
assertThat(response.sequence()).isEqualTo(2);
}

@Test
@DisplayName("존재하지 않는 공고 ID로 ACTUAL 타입 지원 생성 시 예외를 던진다")
void createActualApplyThrowsWhenJobPostingNotFound() {
Expand Down
Loading