diff --git a/.gitmodules b/.gitmodules index 44636311..ffc773e8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ -[submodule "ASSU_config"] - path = ASSU_config - url = https://github.com/ASSU-dev/ASSU_config.git +[submodule "config"] + path = config + url = https://github.com/ASSU-dev/ASSU_BE_config.git +[submodule "manifest"] + path = manifest + url = https://github.com/ASSU-dev/ASSU_BE_manifest.git diff --git a/Dockerfile b/Dockerfile index 517ccb88..99c8958e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ WORKDIR /build COPY --from=dependencies /build /build COPY src src -COPY ASSU_config ASSU_config +COPY config config RUN ./gradlew bootJar -x test --build-cache --no-daemon diff --git a/build.gradle b/build.gradle index 5892b8b3..b513f91d 100644 --- a/build.gradle +++ b/build.gradle @@ -117,9 +117,9 @@ tasks.named('test') { } tasks.register('copyPrivateConfig', Copy) { - from './ASSU_config/local' - from './ASSU_config/dev' - from './ASSU_config/prod' + from './config/local' + from './config/dev' + from './config/prod' into 'src/main/resources' diff --git a/ASSU_config b/config similarity index 100% rename from ASSU_config rename to config diff --git a/manifest b/manifest new file mode 160000 index 00000000..8fcb0e58 --- /dev/null +++ b/manifest @@ -0,0 +1 @@ +Subproject commit 8fcb0e58c6a8c9095d89f7f1446f9a01fdffee41 diff --git a/src/main/java/com/assu/server/domain/admin/controller/AdminController.java b/src/main/java/com/assu/server/domain/admin/controller/AdminController.java index b64aabde..e42c0b84 100644 --- a/src/main/java/com/assu/server/domain/admin/controller/AdminController.java +++ b/src/main/java/com/assu/server/domain/admin/controller/AdminController.java @@ -31,7 +31,7 @@ public class AdminController { " - `partnerAddress` (String): 제휴업체 주소\n" + " - `partnerDetailAddress` (String): 제휴업체 상세주소\n" + " - `partnerName` (String): 제휴업체 상호명\n" + - " - `partnerUrl` (String): 제휴업체 카카오맵 URL\n" + + " - `partnerUrl` (String): 제휴업체 프로필 이미지 URL (S3 주소)\n" + " - `partnerPhone` (String): 제휴업체 전화번호\n") @GetMapping("/partner-recommend") public BaseResponse randomPartnerRecommend( diff --git a/src/main/java/com/assu/server/domain/mapping/controller/StudentAdminController.java b/src/main/java/com/assu/server/domain/admin/controller/StudentAdminController.java similarity index 95% rename from src/main/java/com/assu/server/domain/mapping/controller/StudentAdminController.java rename to src/main/java/com/assu/server/domain/admin/controller/StudentAdminController.java index e2c44822..6ec802bd 100644 --- a/src/main/java/com/assu/server/domain/mapping/controller/StudentAdminController.java +++ b/src/main/java/com/assu/server/domain/admin/controller/StudentAdminController.java @@ -1,7 +1,7 @@ -package com.assu.server.domain.mapping.controller; +package com.assu.server.domain.admin.controller; -import com.assu.server.domain.mapping.dto.StudentAdminResponseDTO; -import com.assu.server.domain.mapping.service.StudentAdminService; +import com.assu.server.domain.admin.dto.StudentAdminResponseDTO; +import com.assu.server.domain.admin.service.StudentAdminService; import com.assu.server.global.apiPayload.BaseResponse; import com.assu.server.global.apiPayload.code.status.SuccessStatus; import com.assu.server.global.util.PrincipalDetails; diff --git a/src/main/java/com/assu/server/domain/admin/dto/AdminResponseDTO.java b/src/main/java/com/assu/server/domain/admin/dto/AdminResponseDTO.java index e5a304f9..d1f5fbe2 100644 --- a/src/main/java/com/assu/server/domain/admin/dto/AdminResponseDTO.java +++ b/src/main/java/com/assu/server/domain/admin/dto/AdminResponseDTO.java @@ -17,7 +17,7 @@ public record AdminResponseDTO ( @Schema(description = "제휴업체 상세주소", example = "2층 201호") String partnerDetailAddress, - @Schema(description = "제휴업체 URL", example = "https://www.beer.co.kr") + @Schema(description = "제휴업체 프로필 이미지 URL (S3 주소)", example = "https://assu-bucket.s3.amazonaws.com/profile.png") String partnerUrl, @Schema(description = "제휴업체 전화번호", example = "02-123-4567") diff --git a/src/main/java/com/assu/server/domain/mapping/dto/StoreUsageWithPaper.java b/src/main/java/com/assu/server/domain/admin/dto/StoreUsageWithPaper.java similarity index 75% rename from src/main/java/com/assu/server/domain/mapping/dto/StoreUsageWithPaper.java rename to src/main/java/com/assu/server/domain/admin/dto/StoreUsageWithPaper.java index 0035feae..451b5889 100644 --- a/src/main/java/com/assu/server/domain/mapping/dto/StoreUsageWithPaper.java +++ b/src/main/java/com/assu/server/domain/admin/dto/StoreUsageWithPaper.java @@ -1,4 +1,4 @@ -package com.assu.server.domain.mapping.dto; +package com.assu.server.domain.admin.dto; public record StoreUsageWithPaper( Long paperId, diff --git a/src/main/java/com/assu/server/domain/admin/dto/StudentAdminRequestDTO.java b/src/main/java/com/assu/server/domain/admin/dto/StudentAdminRequestDTO.java new file mode 100644 index 00000000..c6150a97 --- /dev/null +++ b/src/main/java/com/assu/server/domain/admin/dto/StudentAdminRequestDTO.java @@ -0,0 +1,5 @@ +package com.assu.server.domain.admin.dto; + +public class StudentAdminRequestDTO { + +} diff --git a/src/main/java/com/assu/server/domain/mapping/dto/StudentAdminResponseDTO.java b/src/main/java/com/assu/server/domain/admin/dto/StudentAdminResponseDTO.java similarity index 98% rename from src/main/java/com/assu/server/domain/mapping/dto/StudentAdminResponseDTO.java rename to src/main/java/com/assu/server/domain/admin/dto/StudentAdminResponseDTO.java index 47520a0f..f801725a 100644 --- a/src/main/java/com/assu/server/domain/mapping/dto/StudentAdminResponseDTO.java +++ b/src/main/java/com/assu/server/domain/admin/dto/StudentAdminResponseDTO.java @@ -1,4 +1,4 @@ -package com.assu.server.domain.mapping.dto; +package com.assu.server.domain.admin.dto; import com.assu.server.domain.admin.entity.Admin; import com.assu.server.domain.partnership.entity.Paper; diff --git a/src/main/java/com/assu/server/domain/mapping/entity/StudentAdmin.java b/src/main/java/com/assu/server/domain/admin/entity/StudentAdmin.java similarity index 94% rename from src/main/java/com/assu/server/domain/mapping/entity/StudentAdmin.java rename to src/main/java/com/assu/server/domain/admin/entity/StudentAdmin.java index f43b7044..2a719123 100644 --- a/src/main/java/com/assu/server/domain/mapping/entity/StudentAdmin.java +++ b/src/main/java/com/assu/server/domain/admin/entity/StudentAdmin.java @@ -1,4 +1,4 @@ -package com.assu.server.domain.mapping.entity; +package com.assu.server.domain.admin.entity; import com.assu.server.domain.common.entity.BaseEntity; import com.assu.server.domain.student.entity.Student; diff --git a/src/main/java/com/assu/server/domain/admin/repository/AdminRepository.java b/src/main/java/com/assu/server/domain/admin/repository/AdminRepository.java index f0e5d692..16d878af 100644 --- a/src/main/java/com/assu/server/domain/admin/repository/AdminRepository.java +++ b/src/main/java/com/assu/server/domain/admin/repository/AdminRepository.java @@ -29,42 +29,39 @@ List findMatchingAdmins(@Param("university") University university, @Param("department") Department department, @Param("major") Major major); - // 후보 수 카운트: 해당 partner와 ACTIVE 제휴가 없는 admin 수 - @Query(value = """ - SELECT COUNT(*) - FROM admin a + // 후보 수 카운트 + @Query(""" + SELECT COUNT(a) + FROM Admin a WHERE NOT EXISTS ( - SELECT 1 FROM paper pa - WHERE pa.admin_id = a.id - AND pa.partner_id = :partnerId - AND pa.is_activated = 'ACTIVE' + SELECT 1 FROM Paper pa + WHERE pa.admin = a + AND pa.partner.id = :partnerId + AND pa.isActivated = com.assu.server.domain.common.enums.ActivationStatus.ACTIVE ) - """, nativeQuery = true) - long countPartner(@Param("partnerId") Long partnerId); + """) + long countPartner(@Param("partnerId") Long partnerId); - // 랜덤 오프셋으로 1~N건 가져오기 (LIMIT :offset, :limit) - @Query(value = """ - SELECT a.* - FROM admin a + // 랜덤 오프셋 조회 + @Query(""" + SELECT a + FROM Admin a WHERE NOT EXISTS ( - SELECT 1 FROM paper pa - WHERE pa.admin_id = a.id - AND pa.partner_id = :partnerId - AND pa.is_activated = 'ACTIVE' + SELECT 1 FROM Paper pa + WHERE pa.admin = a + AND pa.partner.id = :partnerId + AND pa.isActivated = com.assu.server.domain.common.enums.ActivationStatus.ACTIVE ) - LIMIT :offset, :limit - """, nativeQuery = true) - List findPartnerWithOffset(@Param("partnerId") Long partnerId, - @Param("offset") int offset, - @Param("limit") int limit); + """) + List findPartnerWithOffset(@Param("partnerId") Long partnerId, Pageable pageable); @Query(""" SELECT DISTINCT a FROM Admin a LEFT JOIN FETCH a.member WHERE a.point IS NOT NULL - AND function('ST_Contains', function('ST_GeomFromText', :wkt, 4326), a.point) = true - """) + AND ST_Contains(ST_GeomFromText(:wkt, 4326), a.point) = true + """) List findAllWithinViewportWithMember(@Param("wkt") String wkt, Pageable pageable); @Query(""" diff --git a/src/main/java/com/assu/server/domain/mapping/repository/StudentAdminRepository.java b/src/main/java/com/assu/server/domain/admin/repository/StudentAdminRepository.java similarity index 82% rename from src/main/java/com/assu/server/domain/mapping/repository/StudentAdminRepository.java rename to src/main/java/com/assu/server/domain/admin/repository/StudentAdminRepository.java index 6a5a3c5c..1082a9e0 100644 --- a/src/main/java/com/assu/server/domain/mapping/repository/StudentAdminRepository.java +++ b/src/main/java/com/assu/server/domain/admin/repository/StudentAdminRepository.java @@ -1,8 +1,7 @@ -package com.assu.server.domain.mapping.repository; +package com.assu.server.domain.admin.repository; -import com.assu.server.domain.mapping.dto.StoreUsageWithPaper; -import com.assu.server.domain.mapping.dto.StudentAdminResponseDTO; -import com.assu.server.domain.mapping.entity.StudentAdmin; +import com.assu.server.domain.admin.dto.StoreUsageWithPaper; +import com.assu.server.domain.admin.entity.StudentAdmin; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -34,7 +33,7 @@ Long countTodayUsersByAdmin( ); @Query(""" - SELECT new com.assu.server.domain.mapping.dto.StoreUsageWithPaper( + SELECT new com.assu.server.domain.admin.dto.StoreUsageWithPaper( p.id, p.store.id, p.store.name, COUNT(pu.id) ) FROM PartnershipUsage pu diff --git a/src/main/java/com/assu/server/domain/admin/service/AdminServiceImpl.java b/src/main/java/com/assu/server/domain/admin/service/AdminServiceImpl.java index 055742b1..50b937c7 100644 --- a/src/main/java/com/assu/server/domain/admin/service/AdminServiceImpl.java +++ b/src/main/java/com/assu/server/domain/admin/service/AdminServiceImpl.java @@ -11,6 +11,8 @@ import com.assu.server.global.apiPayload.code.status.ErrorStatus; import com.assu.server.global.exception.DatabaseException; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,14 +26,11 @@ public class AdminServiceImpl implements AdminService { private final AdminRepository adminRepository; private final PartnerRepository partnerRepository; - @Override - @Transactional - public List findMatchingAdmins(University university, Department department, Major major){ - - List adminList = adminRepository.findMatchingAdmins(university, department, major); - - return adminList; - } + @Override + @Transactional + public List findMatchingAdmins(University university, Department department, Major major){ + return adminRepository.findMatchingAdmins(university, department, major); + } @Override @Transactional(readOnly = true) @@ -40,19 +39,22 @@ public AdminResponseDTO suggestRandomPartner(Long adminId) { Admin admin = adminRepository.findById(adminId) .orElseThrow(() -> new DatabaseException(ErrorStatus.NO_SUCH_ADMIN)); - long total = partnerRepository.countUnpartneredActiveByAdmin(admin.getId()); + long total = partnerRepository.countUnpartneredActiveByAdmin(admin.getId(), com.assu.server.domain.common.enums.ActivationStatus.ACTIVE); if (total <= 0) { throw new DatabaseException(ErrorStatus.NO_AVAILABLE_PARTNER); } int offset = ThreadLocalRandom.current().nextInt((int)total); - Partner picked = partnerRepository.findUnpartneredActiveByAdminWithOffset(admin.getId(), offset); - if(picked == null) { + Pageable pageable = PageRequest.of(offset, 1); + List pickedList = partnerRepository.findUnpartneredActiveByAdminWithOffset(admin.getId(), com.assu.server.domain.common.enums.ActivationStatus.ACTIVE, pageable); + + if (pickedList.isEmpty()) { throw new DatabaseException(ErrorStatus.NO_AVAILABLE_PARTNER); } + Partner picked = pickedList.get(0); + return AdminResponseDTO.from(picked); } - -} +} \ No newline at end of file diff --git a/src/main/java/com/assu/server/domain/mapping/service/StudentAdminService.java b/src/main/java/com/assu/server/domain/admin/service/StudentAdminService.java similarity index 80% rename from src/main/java/com/assu/server/domain/mapping/service/StudentAdminService.java rename to src/main/java/com/assu/server/domain/admin/service/StudentAdminService.java index 9504e7e8..084529e7 100644 --- a/src/main/java/com/assu/server/domain/mapping/service/StudentAdminService.java +++ b/src/main/java/com/assu/server/domain/admin/service/StudentAdminService.java @@ -1,6 +1,6 @@ -package com.assu.server.domain.mapping.service; +package com.assu.server.domain.admin.service; -import com.assu.server.domain.mapping.dto.StudentAdminResponseDTO; +import com.assu.server.domain.admin.dto.StudentAdminResponseDTO; public interface StudentAdminService { StudentAdminResponseDTO.CountAdminAuthResponseDTO getCountAdminAuth(Long memberId); diff --git a/src/main/java/com/assu/server/domain/mapping/service/StudentAdminServiceImpl.java b/src/main/java/com/assu/server/domain/admin/service/StudentAdminServiceImpl.java similarity index 94% rename from src/main/java/com/assu/server/domain/mapping/service/StudentAdminServiceImpl.java rename to src/main/java/com/assu/server/domain/admin/service/StudentAdminServiceImpl.java index 1db0d166..fb8d8895 100644 --- a/src/main/java/com/assu/server/domain/mapping/service/StudentAdminServiceImpl.java +++ b/src/main/java/com/assu/server/domain/admin/service/StudentAdminServiceImpl.java @@ -1,10 +1,10 @@ -package com.assu.server.domain.mapping.service; +package com.assu.server.domain.admin.service; import com.assu.server.domain.admin.entity.Admin; import com.assu.server.domain.admin.repository.AdminRepository; -import com.assu.server.domain.mapping.dto.StoreUsageWithPaper; -import com.assu.server.domain.mapping.dto.StudentAdminResponseDTO; -import com.assu.server.domain.mapping.repository.StudentAdminRepository; +import com.assu.server.domain.admin.dto.StoreUsageWithPaper; +import com.assu.server.domain.admin.dto.StudentAdminResponseDTO; +import com.assu.server.domain.admin.repository.StudentAdminRepository; import com.assu.server.domain.partnership.entity.Paper; import com.assu.server.domain.partnership.repository.PaperRepository; import com.assu.server.global.apiPayload.code.status.ErrorStatus; diff --git a/src/main/java/com/assu/server/domain/mapping/dto/StudentAdminRequestDTO.java b/src/main/java/com/assu/server/domain/mapping/dto/StudentAdminRequestDTO.java deleted file mode 100644 index b4f2c060..00000000 --- a/src/main/java/com/assu/server/domain/mapping/dto/StudentAdminRequestDTO.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.assu.server.domain.mapping.dto; - -public class StudentAdminRequestDTO { - -} diff --git a/src/main/java/com/assu/server/domain/partner/controller/PartnerController.java b/src/main/java/com/assu/server/domain/partner/controller/PartnerController.java index 17ceb7e5..4f0b4683 100644 --- a/src/main/java/com/assu/server/domain/partner/controller/PartnerController.java +++ b/src/main/java/com/assu/server/domain/partner/controller/PartnerController.java @@ -29,7 +29,7 @@ public class PartnerController { " - `adminAddress` (String): 관리자 주소\n" + " - `adminDetailAddress` (String): 관리자 상세주소\n" + " - `adminName` (String): 관리자 상호명\n" + - " - `adminUrl` (String): 관리자 카카오맵 URL\n" + + " - `adminUrl` (String): 관리자 프로필 이미지 URL (S3 주소)\n" + " - `adminPhone` (String): 관리자 전화번호\n") @GetMapping("/admin-recommend") public BaseResponse randomAdminRecommend( diff --git a/src/main/java/com/assu/server/domain/partner/repository/PartnerRepository.java b/src/main/java/com/assu/server/domain/partner/repository/PartnerRepository.java index 7ac8ac32..ecc86fa7 100644 --- a/src/main/java/com/assu/server/domain/partner/repository/PartnerRepository.java +++ b/src/main/java/com/assu/server/domain/partner/repository/PartnerRepository.java @@ -1,6 +1,7 @@ package com.assu.server.domain.partner.repository; import com.assu.server.domain.partner.entity.Partner; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -11,41 +12,41 @@ public interface PartnerRepository extends JpaRepository { boolean existsByPhoneNum(String phoneNum); - // 현재 admin과 'ACTIVE' 상태로 제휴 중인 partner를 제외한 후보 수 - @Query(value = """ - SELECT COUNT(*) - FROM partner p - LEFT JOIN paper pa - ON pa.partner_id = p.id - AND pa.admin_id = :adminId - AND pa.is_activated = 'ACTIVE' - WHERE pa.id IS NULL - """, nativeQuery = true) - long countUnpartneredActiveByAdmin(@Param("adminId") Long adminId); - - // 위 후보들 중에서 offset 하나만 가져오기 (랜덤 오프셋으로 1건) - @Query(value = """ - SELECT p.* - FROM partner p - LEFT JOIN paper pa - ON pa.partner_id = p.id - AND pa.admin_id = :adminId - AND pa.is_activated = 'ACTIVE' - WHERE pa.id IS NULL - LIMIT :offset, 1 - """, nativeQuery = true) - Partner findUnpartneredActiveByAdminWithOffset(@Param("adminId") Long adminId, - @Param("offset") int offset); + @Query(""" + SELECT COUNT(p) + FROM Partner p + WHERE NOT EXISTS ( + SELECT 1 FROM Paper pa + WHERE pa.partner = p + AND pa.admin.id = :adminId + AND pa.isActivated = :status + ) + """) + long countUnpartneredActiveByAdmin(@Param("adminId") Long adminId, @Param("status") com.assu.server.domain.common.enums.ActivationStatus status); + @Query(""" + SELECT p + FROM Partner p + WHERE NOT EXISTS ( + SELECT 1 FROM Paper pa + WHERE pa.partner = p + AND pa.admin.id = :adminId + AND pa.isActivated = :status + ) + """) + List findUnpartneredActiveByAdminWithOffset(@Param("adminId") Long adminId, @Param("status") com.assu.server.domain.common.enums.ActivationStatus status, Pageable pageable); + + // 반경 내 제휴업체 조회 @Query(""" SELECT DISTINCT p FROM Partner p LEFT JOIN FETCH p.member WHERE p.point IS NOT NULL - AND function('ST_Contains', function('ST_GeomFromText', :wkt, 4326), p.point) = true + AND ST_Contains(ST_GeomFromText(:wkt, 4326), p.point) = true """) List findAllWithinViewportWithMember(@Param("wkt") String wkt); + // 키워드 검색 @Query(""" SELECT DISTINCT p FROM Partner p @@ -55,6 +56,4 @@ WHERE LOWER(p.name) LIKE LOWER(CONCAT('%', :keyword, '%')) List searchPartnerByKeywordWithMember( @Param("keyword") String keyword ); - - -} +} \ No newline at end of file diff --git a/src/main/java/com/assu/server/domain/partner/service/PartnerServiceImpl.java b/src/main/java/com/assu/server/domain/partner/service/PartnerServiceImpl.java index 6340f945..9892a918 100644 --- a/src/main/java/com/assu/server/domain/partner/service/PartnerServiceImpl.java +++ b/src/main/java/com/assu/server/domain/partner/service/PartnerServiceImpl.java @@ -11,6 +11,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import java.util.List; import java.util.concurrent.ThreadLocalRandom; @@ -41,8 +43,8 @@ public PartnerResponseDTO getRandomAdmin(Long partnerId) { offset = ThreadLocalRandom.current().nextInt(0, (int)(total - limit + 1)); } - List picked = adminRepository.findPartnerWithOffset(partner.getId(), offset, limit); - + Pageable pageable = PageRequest.of(offset, limit); + List picked = adminRepository.findPartnerWithOffset(partner.getId(), pageable); List admins = picked.stream() .map(PartnerResponseDTO.AdminLiteDTO::from) .collect(Collectors.toList());