From 75df0470550bc36e44f5f10f4bf30c64c3a2dfed Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 9 Sep 2024 17:04:17 +0900 Subject: [PATCH 001/108] =?UTF-8?q?[IDLE-000]=20Production=20CI=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-server-deployer.yaml | 4 +- .github/workflows/prod-server-integrator.yaml | 41 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/prod-server-integrator.yaml diff --git a/.github/workflows/prod-server-deployer.yaml b/.github/workflows/prod-server-deployer.yaml index 5863766f..510c0277 100644 --- a/.github/workflows/prod-server-deployer.yaml +++ b/.github/workflows/prod-server-deployer.yaml @@ -81,10 +81,10 @@ jobs: key: ${{ secrets.INSTANCE_PEM_KEY }} script: | sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} - sudo docker pull public.ecr.aws/f5q3r6m5/idle-ecr:$IMAGE_TAG + sudo docker pull public.ecr.aws/f5q3r6m5/idle-prod-ecr:$IMAGE_TAG sudo docker stop caremeet_server_prod || true sudo docker rm caremeet_server_prod || true - sudo docker run --name caremeet_server_prod --env-file ./.env -d -p 8080:8080 public.ecr.aws/f5q3r6m5/idle-ecr:$IMAGE_TAG + sudo docker run --name caremeet_server_prod --env-file ./.env -d -p 8080:8080 public.ecr.aws/f5q3r6m5/idle-prod-ecr:$IMAGE_TAG - name: Remove GitHub Actions IP run: | diff --git a/.github/workflows/prod-server-integrator.yaml b/.github/workflows/prod-server-integrator.yaml new file mode 100644 index 00000000..7e77ae7b --- /dev/null +++ b/.github/workflows/prod-server-integrator.yaml @@ -0,0 +1,41 @@ +name: Production Server Integrator (CI) + +on: + push: + branches: + - main + +jobs: + build_and_push: + runs-on: ubuntu-latest + steps: + - name: Check Out Repository + uses: actions/checkout@v4 + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-1 + + - name: Login to Amazon ECR Public + id: login-ecr-public + uses: aws-actions/amazon-ecr-login@v2 + with: + registry-type: public + + - name: Build, tag, and push docker image to Amazon ECR Public + env: + REGISTRY: ${{ steps.login-ecr-public.outputs.registry }} + REGISTRY_ALIAS: ${{ secrets.ECR_REGISTRY_ALIAS }} + REPOSITORY: idle-prod-ecr + IMAGE_TAG: latest + run: | + echo "REPOSITORY: $REPOSITORY" + docker build -t $REGISTRY/$REGISTRY_ALIAS/$REPOSITORY:$IMAGE_TAG . + docker push $REGISTRY/$REGISTRY_ALIAS/$REPOSITORY:$IMAGE_TAG + echo "::set-output name=image::$REGISTRY/$REGISTRY_ALIAS/$REPOSITORY:$IMAGE_TAG" + + - name: Logout of Amazon ECR + run: docker logout ${{ env.ECR_REGISTRY }} From 32bae8bc1fc4229540ef994948a3cb298d75a249 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 9 Sep 2024 17:51:38 +0900 Subject: [PATCH 002/108] =?UTF-8?q?[IDLE-000]=20=EC=84=BC=ED=84=B0=20?= =?UTF-8?q?=EA=B3=B5=EA=B3=A0=20=EC=88=98=EC=A0=95=20API=20=EB=82=B4=20?= =?UTF-8?q?=EC=A0=91=EC=88=98=20=EB=B0=A9=EB=B2=95=20null=20=EB=B9=84?= =?UTF-8?q?=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transfer/jobposting/center/UpdateJobPostingRequest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/center/UpdateJobPostingRequest.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/center/UpdateJobPostingRequest.kt index 165a64d9..a05e5c69 100644 --- a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/center/UpdateJobPostingRequest.kt +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/center/UpdateJobPostingRequest.kt @@ -64,7 +64,7 @@ data class UpdateJobPostingRequest( @Schema(description = "경력자 우대 여부", name = "isExperiencePreferred") val isExperiencePreferred: Boolean?, @Schema(description = "접수 방법", example = "[CALLING, MESSAGE]") - val applyMethod: List?, + val applyMethod: List, @Schema(description = "접수 마감 일자") val applyDeadline: String? = null, @Schema(description = "접수 마감일 상태") From cf9e3a020439bd79bf9b6ab472e3740d485c26c5 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 9 Sep 2024 18:01:10 +0900 Subject: [PATCH 003/108] =?UTF-8?q?[IDLE-000]=20=EA=B3=B5=EA=B3=A0=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90=EC=9E=90=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C,?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=EB=90=9C=20=EC=9C=A0=EC=A0=80=EB=8A=94=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../facade/CenterJobPostingFacadeService.kt | 12 ++++++++---- .../common/service/domain/DeletedUserInfoService.kt | 12 +++++++++--- ...Repository.kt => DeletedUserInfoJpaRepository.kt} | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) rename idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/repository/jpa/{DeletedUserInfoRepository.kt => DeletedUserInfoJpaRepository.kt} (71%) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CenterJobPostingFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CenterJobPostingFacadeService.kt index d3dd47c1..2b032e7a 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CenterJobPostingFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CenterJobPostingFacadeService.kt @@ -11,6 +11,7 @@ import com.swm.idle.application.jobposting.vo.JobPostingInfo import com.swm.idle.application.user.carer.domain.CarerService import com.swm.idle.application.user.center.service.domain.CenterManagerService import com.swm.idle.application.user.center.service.domain.CenterService +import com.swm.idle.application.user.common.service.domain.DeletedUserInfoService import com.swm.idle.domain.jobposting.entity.jpa.JobPosting import com.swm.idle.domain.user.carer.entity.jpa.Carer import com.swm.idle.domain.user.center.exception.CenterException @@ -41,6 +42,7 @@ class CenterJobPostingFacadeService( private val carerService: CarerService, private val carerApplyService: CarerApplyService, private val applicantService: ApplicantService, + private val deletedUserInfoService: DeletedUserInfoService, ) { @Transactional @@ -163,10 +165,10 @@ class CenterJobPostingFacadeService( ) } - request.applyMethod?.let { + request.applyMethod.let { jobPostingApplyMethodService.update( jobPosting = jobPosting, - applyMethods = request.applyMethod!!, + applyMethods = request.applyMethod, ) } } @@ -240,8 +242,10 @@ class CenterJobPostingFacadeService( fun getJobPostingApplicants(jobPostingId: UUID): JobPostingApplicantsResponse { val applys = carerApplyService.findAllByJobPostingId(jobPostingId) - val applicants: List = applys.map { apply -> - carerService.getById(apply.carerId) + val applicants: List = applys.mapNotNull { apply -> + carerService.getById(apply.carerId).takeIf { + deletedUserInfoService.findById(apply.carerId) == null + } } val jobPosting = jobPostingService.getById(jobPostingId) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/domain/DeletedUserInfoService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/domain/DeletedUserInfoService.kt index 520be2f4..a05d1ac0 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/domain/DeletedUserInfoService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/domain/DeletedUserInfoService.kt @@ -2,16 +2,18 @@ package com.swm.idle.application.user.common.service.domain import com.swm.idle.domain.user.common.entity.jpa.DeletedUserInfo import com.swm.idle.domain.user.common.enum.UserType -import com.swm.idle.domain.user.common.repository.jpa.DeletedUserInfoRepository +import com.swm.idle.domain.user.common.repository.jpa.DeletedUserInfoJpaRepository import com.swm.idle.domain.user.common.vo.PhoneNumber import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.time.LocalDateTime import java.util.* +import kotlin.jvm.optionals.getOrNull @Service +@Transactional(readOnly = true) class DeletedUserInfoService( - private val deletedUserInfoRepository: DeletedUserInfoRepository, + private val deletedUserInfoJpaRepository: DeletedUserInfoJpaRepository, ) { @Transactional @@ -21,7 +23,7 @@ class DeletedUserInfoService( role: UserType, reason: String, ) { - deletedUserInfoRepository.save( + deletedUserInfoJpaRepository.save( DeletedUserInfo( id = id, phoneNumber = phoneNumber.value, @@ -32,4 +34,8 @@ class DeletedUserInfoService( ) } + fun findById(carerId: UUID): DeletedUserInfo? { + return deletedUserInfoJpaRepository.findById(carerId).getOrNull() + } + } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/repository/jpa/DeletedUserInfoRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/repository/jpa/DeletedUserInfoJpaRepository.kt similarity index 71% rename from idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/repository/jpa/DeletedUserInfoRepository.kt rename to idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/repository/jpa/DeletedUserInfoJpaRepository.kt index 48e116ab..2a70d743 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/repository/jpa/DeletedUserInfoRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/repository/jpa/DeletedUserInfoJpaRepository.kt @@ -4,5 +4,5 @@ import com.swm.idle.domain.user.common.entity.jpa.DeletedUserInfo import org.springframework.data.jpa.repository.JpaRepository import java.util.* -interface DeletedUserInfoRepository : JpaRepository { +interface DeletedUserInfoJpaRepository : JpaRepository { } From 34367cd0b52a292a91467538b295bcba3c416658 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 9 Sep 2024 19:06:41 +0900 Subject: [PATCH 004/108] =?UTF-8?q?[IDLE-363]=20=EC=84=BC=ED=84=B0=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=EC=A0=84=ED=99=94=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=9A=94=EC=B2=AD=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/user/carer/domain/CarerService.kt | 2 -- .../center/service/domain/CenterManagerService.kt | 8 +++++--- .../center/service/facade/CenterAuthFacadeService.kt | 9 +++++++++ .../swm/idle/domain/user/carer/entity/jpa/Carer.kt | 4 +--- .../domain/user/center/entity/jpa/CenterManager.kt | 8 +++++--- .../user/center/enums/CenterManagerAccountStatus.kt | 1 + .../swm/idle/domain/user/common/entity/jpa/User.kt | 11 ++--------- .../presentation/auth/center/api/CenterAuthApi.kt | 6 ++++++ .../auth/center/controller/CenterAuthController.kt | 4 ++++ 9 files changed, 33 insertions(+), 20 deletions(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/carer/domain/CarerService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/carer/domain/CarerService.kt index 23bbaa75..f1f69210 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/user/carer/domain/CarerService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/carer/domain/CarerService.kt @@ -7,7 +7,6 @@ import com.swm.idle.domain.user.carer.repository.jpa.CarerJpaRepository import com.swm.idle.domain.user.common.enum.GenderType import com.swm.idle.domain.user.common.vo.BirthYear import com.swm.idle.domain.user.common.vo.PhoneNumber -import com.swm.idle.support.common.uuid.UuidCreator import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -32,7 +31,6 @@ class CarerService( ): Carer { return carerJpaRepository.save( Carer( - id = UuidCreator.create(), birthYear = birthYear.value, carerName = carerName, gender = gender, diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerService.kt index 911ab95d..c0e5c42e 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerService.kt @@ -10,7 +10,6 @@ import com.swm.idle.domain.user.center.vo.Identifier import com.swm.idle.domain.user.center.vo.Password import com.swm.idle.domain.user.common.vo.PhoneNumber import com.swm.idle.support.common.encrypt.PasswordEncryptor -import com.swm.idle.support.common.uuid.UuidCreator import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.util.* @@ -31,12 +30,11 @@ class CenterManagerService( val encryptedPassword = PasswordEncryptor.encrypt(rawPassword = password.value) CenterManager( - id = UuidCreator.create(), identifier = identifier.value, password = encryptedPassword, phoneNumber = phoneNumber.value, managerName = managerName, - status = CenterManagerAccountStatus.PENDING, + status = CenterManagerAccountStatus.NEW, centerBusinessRegistrationNumber = centerBusinessRegistrationNumber.value, ).also { centerManagerJpaRepository.save(it) @@ -83,4 +81,8 @@ class CenterManagerService( ?: throw PersistenceException.ResourceNotFound("등록되지 않은 전화번호(phoneNumber: ${phoneNumber.value}입니다.") } + fun updateAccountStatusToPending(centerManager: CenterManager) { + centerManager.updateAccountStatusToPending() + } + } diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt index c8d3f6b4..63b75316 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt @@ -5,6 +5,7 @@ import com.swm.idle.application.user.center.service.domain.CenterManagerService import com.swm.idle.application.user.common.service.domain.DeletedUserInfoService import com.swm.idle.application.user.common.service.domain.RefreshTokenService import com.swm.idle.application.user.common.service.util.JwtTokenService +import com.swm.idle.domain.common.enums.EntityStatus import com.swm.idle.domain.common.exception.PersistenceException import com.swm.idle.domain.user.center.exception.CenterException import com.swm.idle.domain.user.center.vo.BusinessRegistrationNumber @@ -135,4 +136,12 @@ class CenterAuthFacadeService( centerManagerService.updatePassword(centerManager, newPassword) } + @Transactional + fun requestCenterManagerVerification() { + getUserAuthentication().userId + .let { centerManagerService.getById(it) } + .takeIf { it.entityStatus == EntityStatus.ACTIVE } + ?.let { centerManagerService.updateAccountStatusToPending(it) } + } + } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/carer/entity/jpa/Carer.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/carer/entity/jpa/Carer.kt index 64b2ae89..7c012192 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/carer/entity/jpa/Carer.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/carer/entity/jpa/Carer.kt @@ -11,13 +11,11 @@ import jakarta.persistence.Enumerated import jakarta.persistence.Table import org.hibernate.annotations.DynamicUpdate import java.math.BigDecimal -import java.util.* @Entity @Table(name = "carer") @DynamicUpdate class Carer( - id: UUID, phoneNumber: String, carerName: String, birthYear: Int, @@ -32,7 +30,7 @@ class Carer( profileImageUrl: String? = null, jobSearchStatus: JobSearchStatus = JobSearchStatus.YES, carerAccountStatus: CarerAccountStatus = CarerAccountStatus.ACTIVE, -) : User(id, phoneNumber, carerName) { +) : User(phoneNumber, carerName) { @Column(nullable = false) var birthYear: Int = birthYear diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/entity/jpa/CenterManager.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/entity/jpa/CenterManager.kt index e3eb4831..ca9c83ec 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/entity/jpa/CenterManager.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/entity/jpa/CenterManager.kt @@ -7,19 +7,17 @@ import jakarta.persistence.Entity import jakarta.persistence.EnumType import jakarta.persistence.Enumerated import jakarta.persistence.Table -import java.util.* @Entity @Table(name = "center_manager") class CenterManager( - id: UUID, identifier: String, password: String, managerName: String, phoneNumber: String, status: CenterManagerAccountStatus, centerBusinessRegistrationNumber: String, -) : User(id, phoneNumber, managerName) { +) : User(phoneNumber, managerName) { @Column(nullable = false, columnDefinition = "varchar(255)") var identifier: String = identifier @@ -42,4 +40,8 @@ class CenterManager( this.password = newPassword } + fun updateAccountStatusToPending() { + this.status = CenterManagerAccountStatus.PENDING + } + } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/enums/CenterManagerAccountStatus.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/enums/CenterManagerAccountStatus.kt index f809c006..06c05eeb 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/enums/CenterManagerAccountStatus.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/enums/CenterManagerAccountStatus.kt @@ -1,6 +1,7 @@ package com.swm.idle.domain.user.center.enums enum class CenterManagerAccountStatus { + NEW, PENDING, APPROVED, } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/entity/jpa/User.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/entity/jpa/User.kt index bb122986..ef078f56 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/entity/jpa/User.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/entity/jpa/User.kt @@ -1,21 +1,14 @@ package com.swm.idle.domain.user.common.entity.jpa +import com.swm.idle.domain.common.entity.BaseEntity import jakarta.persistence.Column -import jakarta.persistence.Id import jakarta.persistence.MappedSuperclass -import java.util.* @MappedSuperclass open class User( - id: UUID, phoneNumber: String, name: String, -) { - - @Id - @Column(nullable = false) - var id: UUID = id - private set +) : BaseEntity() { @Column(nullable = false, columnDefinition = "varchar(255)") var phoneNumber: String = phoneNumber diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/auth/center/api/CenterAuthApi.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/auth/center/api/CenterAuthApi.kt index c763dd77..cc483d83 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/auth/center/api/CenterAuthApi.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/auth/center/api/CenterAuthApi.kt @@ -41,6 +41,12 @@ interface CenterAuthApi { @ResponseStatus(HttpStatus.OK) fun getJoinStatusInfo(): JoinStatusInfoResponse + @Secured + @Operation(summary = "센터 관리자 전화 인증 요청 API") + @PatchMapping("/join/verify") + @ResponseStatus(HttpStatus.NO_CONTENT) + fun requestCenterManagerVerification() + @Operation(summary = "사업자 등록번호 인증 API") @GetMapping("/authentication/{business-registration-number}") @ResponseStatus(HttpStatus.OK) diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/auth/center/controller/CenterAuthController.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/auth/center/controller/CenterAuthController.kt index 9626d7d6..9b59cb1d 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/auth/center/controller/CenterAuthController.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/auth/center/controller/CenterAuthController.kt @@ -34,6 +34,10 @@ class CenterAuthController( return centerAuthFacadeService.getCenterManagerJoinStatusInfo() } + override fun requestCenterManagerVerification() { + return centerAuthFacadeService.requestCenterManagerVerification() + } + override fun validateBusinessRegistrationNumber(businessRegistrationNumber: String): ValidateBusinessRegistrationNumberResponse { return centerAuthFacadeService.validateCompany( businessRegistrationNumber = BusinessRegistrationNumber(businessRegistrationNumber), From d9b07a461e53d88e541fb6e1949c6807d6aa6bf1 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 9 Sep 2024 19:07:26 +0900 Subject: [PATCH 005/108] =?UTF-8?q?[IDLE-363]=20=EA=B0=9C=EB=B0=9C=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20ddl-auto=20=EC=98=B5=EC=85=98=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=EB=A1=9C=20create=20=EC=98=B5=EC=85=98=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idle-domain/src/main/resources/application-domain.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-domain/src/main/resources/application-domain.yml b/idle-domain/src/main/resources/application-domain.yml index 35a7b5ed..c642fdaf 100644 --- a/idle-domain/src/main/resources/application-domain.yml +++ b/idle-domain/src/main/resources/application-domain.yml @@ -31,5 +31,5 @@ spring: on-profile: dev jpa: hibernate: - ddl-auto: validate + ddl-auto: create show-sql: false From 7f8cac9e29478183de9ccd8f1427ccae00f73674 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 10 Sep 2024 21:20:36 +0900 Subject: [PATCH 006/108] =?UTF-8?q?[IDLE-365]=20=EA=B3=B5=EA=B3=A0=20?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=EB=9F=AC=20selenium=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EB=A1=9C=EC=BB=AC=20=EB=8F=99?= =?UTF-8?q?=EC=9E=91=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/converter/PointConverter.kt | 5 +- .../facade/CrawlingJobPostingFacadeService.kt | 3 +- .../batch/common/dto/CrawledJobPostingDto.kt | 12 +- .../batch/job/CrawlingJobPostingTasklet.kt | 26 ++- .../com/swm/idle/batch/util/WorknetCrawler.kt | 159 ++++++++++++------ .../src/main/resources/application-batch.yml | 2 +- .../entity/jpa/CrawledJobPosting.kt | 78 ++++----- .../jpa/CrawlingJobPostingJpaRepository.kt | 1 - .../CrawlingJobPostingFavoriteResponse.kt | 14 +- .../common/CrawlingJobPostingResponse.kt | 32 ++-- 10 files changed, 197 insertions(+), 135 deletions(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/common/converter/PointConverter.kt b/idle-application/src/main/kotlin/com/swm/idle/application/common/converter/PointConverter.kt index 0a89dda6..f880769b 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/common/converter/PointConverter.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/common/converter/PointConverter.kt @@ -18,7 +18,10 @@ object PointConverter { latitude: Double, longitude: Double, ): Point { - return geometryFactory.createPoint(Coordinate(longitude, latitude)) + val correctedLongitude = if (longitude > latitude) longitude else latitude + val correctedLatitude = if (longitude > latitude) latitude else longitude + + return geometryFactory.createPoint(Coordinate(correctedLongitude, correctedLatitude)) } } diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt index 4d2716ff..e3cdf113 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt @@ -42,7 +42,8 @@ class CrawlingJobPostingFacadeService( ) return crawlingJobPostingService.getById(crawlingJobPostingId).let { - val isFavorite = jobPostingFavoriteService.existsByJobPostingId(crawlingJobPostingId) + val isFavorite = + jobPostingFavoriteService.existsByJobPostingId(crawlingJobPostingId) CrawlingJobPostingResponse.from( crawlingJobPosting = it, diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/dto/CrawledJobPostingDto.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/dto/CrawledJobPostingDto.kt index 95654ac7..69955c74 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/dto/CrawledJobPostingDto.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/dto/CrawledJobPostingDto.kt @@ -3,7 +3,6 @@ package com.swm.idle.batch.common.dto import com.swm.idle.domain.jobposting.entity.jpa.CrawledJobPosting import com.swm.idle.support.common.uuid.UuidCreator import org.locationtech.jts.geom.Point -import java.time.LocalDate import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -24,15 +23,6 @@ data class CrawledJobPostingDto( val directUrl: String, ) { - fun parseApplyDeadline(applyDeadline: String): LocalDate { - return if (applyDeadline.contains("채용시까지")) { - LocalDate.now().plusMonths(1) - } else { - val dateString = applyDeadline.substringBefore("마감시간").trim() - LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyy.MM.dd")) - } - } - fun toDomain(location: Point): CrawledJobPosting { return CrawledJobPosting( id = UuidCreator.create(), @@ -46,7 +36,7 @@ data class CrawledJobPostingDto( payInfo = payInfo, workTime = workTime, workSchedule = workSchedule, - applyDeadline = parseApplyDeadline(applyDeadline), + applyDeadline = applyDeadline, recruitmentProcess = recruitmentProcess, applyMethod = applyMethod, requiredDocument = requiredDocument, diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobPostingTasklet.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobPostingTasklet.kt index 1a545506..a3a0c993 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobPostingTasklet.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobPostingTasklet.kt @@ -10,6 +10,7 @@ import org.springframework.batch.core.scope.context.ChunkContext import org.springframework.batch.core.step.tasklet.Tasklet import org.springframework.batch.repeat.RepeatStatus import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional @Component class CrawlingJobPostingTasklet( @@ -17,12 +18,18 @@ class CrawlingJobPostingTasklet( private val geoCodeService: GeoCodeService, ) : Tasklet { + @Transactional override fun execute(contribution: StepContribution, chunkContext: ChunkContext): RepeatStatus { val crawlingJobPostings: List? = WorknetCrawler.run() if (crawlingJobPostings != null) { - crawlingJobPostings.map { crawledJobPosting -> - val clientLocationInfo = geoCodeService.search(crawledJobPosting.clientAddress) + crawlingJobPostings.mapNotNull { crawledJobPosting -> + val clientRoadNameAddress = extractRoadNameAddress(crawledJobPosting.clientAddress) + val clientLocationInfo = geoCodeService.search(clientRoadNameAddress) + + if (clientLocationInfo.addresses.isEmpty()) { + return@mapNotNull null + } val clientLocation = PointConverter.convertToPoint( latitude = clientLocationInfo.addresses[0].y.toDouble(), @@ -46,11 +53,26 @@ class CrawlingJobPostingTasklet( directUrl = crawledJobPosting.directUrl, ).toDomain(clientLocation) }.let { + println("크롤링된 data 크기 : ${it.size}") crawlingJobPostingService.saveAll(it) } + + return RepeatStatus.FINISHED } return RepeatStatus.FINISHED } + private fun extractRoadNameAddress(clientAddress: String): String { + return clientAddress.replace(Regex(REGEX_FORMAT), "") + .substringBefore(SPLIT_DELIMITER) + .trim() + } + + companion object { + + const val REGEX_FORMAT = "\\(.*?\\)" + const val SPLIT_DELIMITER = "," + } + } diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt index 20011f92..209445c6 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt @@ -1,7 +1,9 @@ package com.swm.idle.batch.util import com.swm.idle.batch.common.dto.CrawledJobPostingDto +import org.openqa.selenium.Alert import org.openqa.selenium.By +import org.openqa.selenium.NoAlertPresentException import org.openqa.selenium.WebDriver import org.openqa.selenium.chrome.ChromeDriver import org.openqa.selenium.support.ui.ExpectedConditions @@ -21,7 +23,8 @@ object WorknetCrawler { fun run(): List? { val formatter = DateTimeFormatter.ofPattern("yyyyMMdd") - val today = LocalDate.now().minusDays(1).format(formatter) +// val today = LocalDate.now().minusDays(1).format(formatter) + val today = LocalDate.now().format(formatter) val crawlingUrl = CRAWLING_TARGET_URL_FORMAT .replace("{today}", today) .replace("{pageIndex}", "1") @@ -38,7 +41,7 @@ object WorknetCrawler { val pageCount = jobPostingCount / JOB_POSTING_COUNT_PER_PAGE - for (i in 1..pageCount) { + for (i in 1..2) { if (i >= 2) { val updatedCrawlingUrl = crawlingUrl .replace("{today}", today) @@ -70,67 +73,92 @@ object WorknetCrawler { return postings } + private fun handleAlertIfPresent() { + try { + val alert: Alert = driver.switchTo().alert() + println("Alert detected: ${alert.text}") + alert.accept() // Alert 창의 '확인'을 누름 + } catch (e: NoAlertPresentException) { + // 알림창이 없으면 무시하고 넘어감 + } + } + private fun crawlPosts( start: Int, end: Int, postings: MutableList, ) { for (i in start..end) { - val originalWindow = driver.windowHandle + try { + val originalWindow = driver.windowHandle + + val em = driver.findElement(By.id("list$i")) + val thirdTd = em.findElements(By.tagName("td"))[2] + val jobPostingDetail = thirdTd.findElement(By.cssSelector(".cp-info .cp-info-in a")) + jobPostingDetail.click() - val em = driver.findElement(By.id("list$i")) - val thirdTd = em.findElements(By.tagName("td"))[2] - val jobPostingDetail = thirdTd.findElement(By.cssSelector(".cp-info .cp-info-in a")) - jobPostingDetail.click() + handleAlertIfPresent() - val wait = WebDriverWait(driver, Duration.ofSeconds(20)) - wait.until(ExpectedConditions.numberOfWindowsToBe(2)) + val wait = WebDriverWait(driver, Duration.ofSeconds(2)) + wait.until(ExpectedConditions.numberOfWindowsToBe(2)) - val allWindows = driver.windowHandles + val allWindows = driver.windowHandles - for (windowHandle in allWindows) { - if (windowHandle != originalWindow) { - driver.switchTo().window(windowHandle) - break + for (windowHandle in allWindows) { + if (windowHandle != originalWindow) { + driver.switchTo().window(windowHandle) + break + } } - } - val crawledJobPostingDto = CrawledJobPostingDto( - title = getTitle(), - content = getContent(), - clientAddress = getClientAddress(), - createdAt = getCreatedAt(), - payInfo = getPayInfo(), - workTime = getWorkTime(), - workSchedule = getWorkSchedule(), - applyDeadline = getApplyDeadline(), - recruitmentProcess = getRecruitmentProcess(), - applyMethod = getApplyMethod(), - requiredDocument = getRequiredDocument(), - centerName = getCenterName(), - centerAddress = getCenterAddress(), - directUrl = driver.currentUrl, - ) - - postings.add(crawledJobPostingDto) - - driver.close() - driver.switchTo().window(originalWindow) + val crawledJobPostingDto = CrawledJobPostingDto( + title = getTitle(), + content = getContent(), + clientAddress = getClientAddress(), + createdAt = getCreatedAt(), + payInfo = getPayInfo(), + workTime = getWorkTime(), + workSchedule = getWorkSchedule(), + applyDeadline = getApplyDeadline(), + recruitmentProcess = getRecruitmentProcess(), + applyMethod = getApplyMethod(), + requiredDocument = getRequiredDocument(), + centerName = getCenterName(), + centerAddress = getCenterAddress(), + directUrl = driver.currentUrl, + ) + + postings.add(crawledJobPostingDto) + + driver.close() + driver.switchTo().window(originalWindow) + } catch (e: Exception) { + println("Error crawling job posting $i: ${e.message}") + handleAlertIfPresent() + } } } private fun getClientAddress(): String { - try { - val address = - driver.findElement(By.xpath("//*[@id=\"contents\"]/section/div/div[3]/div[15]/div/table/tbody/tr[4]/td/p[2]")).text - return address.replace("지도보기", "").trim() - } catch (e: Exception) { - val address = - driver.findElement(By.xpath("//*[@id=\"contents\"]/section/div/div[3]/div[17]/div/table/tbody/tr[4]/td/p[2]")).text - return address.replace("지도보기", "").trim() + val xpaths = listOf( + "//*[@id=\"contents\"]/section/div/div[3]/div[15]/div/table/tbody/tr[4]/td/p[2]", + "//*[@id=\"contents\"]/section/div/div[3]/div[17]/div/table/tbody/tr[4]/td/p[2]", + "//*[@id=\"contents\"]/section/div/div[3]/div[16]/div/table/tbody/tr[4]/td/p[2]" + ) + + for (xpath in xpaths) { + try { + val address = driver.findElement(By.xpath(xpath)).text + return address.replace("지도보기", "").trim() + } catch (e: Exception) { + // Ignore and try the next XPath + } } + + throw NoSuchElementException("클라이언트 주소 크롤링 에러") } + private fun getRequiredDocument(): String { return driver.findElement(By.xpath("//*[@id=\"contents\"]/section/div/div[3]/div[7]/table/tbody/tr/td[4]")).text } @@ -173,25 +201,44 @@ object WorknetCrawler { } private fun getCreatedAt(): String { - try { - return driver.findElement(By.xpath("//*[@id=\"contents\"]/section/div/div[3]/div[16]/table/tbody/tr/td[1]")).text - } catch (e: Exception) { - return driver.findElement(By.xpath("//*[@id=\"contents\"]/section/div/div[3]/div[18]/table/tbody/tr/td[1]")).text + val xpaths = listOf( + "//*[@id=\"contents\"]/section/div/div[3]/div[16]/table/tbody/tr/td[1]", + "//*[@id=\"contents\"]/section/div/div[3]/div[18]/table/tbody/tr/td[1]", + "//*[@id=\"contents\"]/section/div/div[3]/div[17]/table/tbody/tr/td[1]" + ) + + for (xpath in xpaths) { + try { + return driver.findElement(By.xpath(xpath)).text + } catch (e: Exception) { + // Ignore and try the next XPath + } } + + throw NoSuchElementException("CreatedAt element not found using any of the provided XPaths") } + private fun getCenterAddress(): String { - try { - val address = - driver.findElement(By.xpath("//*[@id=\"contents\"]/section/div/div[3]/div[15]/div/table/tbody/tr[1]/td")).text - return address.replace("지도보기", "").trim().replace(Regex("\\(\\d{5}\\)"), "").trim() - } catch (e: Exception) { - val address = - driver.findElement(By.xpath("//*[@id=\"contents\"]/section/div/div[3]/div[17]/div/table/tbody/tr[1]/td")).text - return address.replace("지도보기", "").trim().replace(Regex("\\(\\d{5}\\)"), "").trim() + val xpaths = listOf( + "//*[@id=\"contents\"]/section/div/div[3]/div[15]/div/table/tbody/tr[1]/td", + "//*[@id=\"contents\"]/section/div/div[3]/div[17]/div/table/tbody/tr[1]/td", + "//*[@id=\"contents\"]/section/div/div[3]/div[16]/div/table/tbody/tr[4]/td/p[2]" + ) + + for (xpath in xpaths) { + try { + val address = driver.findElement(By.xpath(xpath)).text + return address.replace("지도보기", "").trim().replace(Regex("\\(\\d{5}\\)"), "").trim() + } catch (e: Exception) { + // Ignore and try the next XPath + } } + + throw NoSuchElementException("Center address not found using any of the provided XPaths") } + private fun getContent(): String { return driver.findElement(By.xpath("//*[@id=\"contents\"]/section/div/div[3]/div[3]/table/tbody/tr/td")).text } diff --git a/idle-batch/src/main/resources/application-batch.yml b/idle-batch/src/main/resources/application-batch.yml index 4cde540b..88067df8 100644 --- a/idle-batch/src/main/resources/application-batch.yml +++ b/idle-batch/src/main/resources/application-batch.yml @@ -3,4 +3,4 @@ spring: jdbc: initialize-schema: never job: - enabled: false + enabled: true diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt index b0a12723..45bfff2f 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt @@ -5,7 +5,6 @@ import jakarta.persistence.Entity import jakarta.persistence.Id import jakarta.persistence.Table import org.locationtech.jts.geom.Point -import java.time.LocalDate import java.time.LocalDateTime import java.util.* @@ -13,84 +12,85 @@ import java.util.* @Table(name = "crawled_job_posting") class CrawledJobPosting( id: UUID, - title: String, - content: String, + title: String?, + content: String?, clientAddress: String, - payInfo: String, - workTime: String, - workSchedule: String, - applyDeadline: LocalDate, - recruitmentProcess: String, - applyMethod: String, - requiredDocument: String, - centerName: String, + payInfo: String?, + workTime: String?, + workSchedule: String?, + applyDeadline: String?, + recruitmentProcess: String?, + applyMethod: String?, + requiredDocument: String?, + centerName: String?, centerAddress: String, - directUrl: String, - createdAt: LocalDateTime, + directUrl: String?, + createdAt: LocalDateTime?, location: Point, ) { @Id - @Column(nullable = false) + @Column(nullable = true) var id: UUID = id private set - @Column(columnDefinition = "varchar(255)") - var title: String = title + @Column(columnDefinition = "varchar(255)", nullable = true) + var title: String? = title private set - @Column(columnDefinition = "TEXT") - var content: String = content + @Column(columnDefinition = "TEXT", nullable = true) + var content: String? = content private set - @Column(columnDefinition = "varchar(255)") + @Column(columnDefinition = "varchar(255)", nullable = true) var clientAddress: String = clientAddress private set - @Column(columnDefinition = "varchar(255)") - var payInfo: String = payInfo + @Column(columnDefinition = "varchar(255)", nullable = true) + var payInfo: String? = payInfo private set - @Column(columnDefinition = "varchar(255)") - var workTime: String = workTime + @Column(columnDefinition = "varchar(255)", nullable = true) + var workTime: String? = workTime private set - @Column(columnDefinition = "varchar(255)") - var workSchedule: String = workSchedule + @Column(columnDefinition = "varchar(255)", nullable = true) + var workSchedule: String? = workSchedule private set - var applyDeadline: LocalDate = applyDeadline + @Column(nullable = true) + var applyDeadline: String? = applyDeadline private set - @Column(columnDefinition = "varchar(255)") - var recruitmentProcess: String = recruitmentProcess + @Column(columnDefinition = "varchar(255)", nullable = true) + var recruitmentProcess: String? = recruitmentProcess private set - @Column(columnDefinition = "varchar(255)") - var applyMethod: String = applyMethod + @Column(columnDefinition = "varchar(255)", nullable = true) + var applyMethod: String? = applyMethod private set - @Column(columnDefinition = "varchar(255)") - var requiredDocument: String = requiredDocument + @Column(columnDefinition = "varchar(255)", nullable = true) + var requiredDocument: String? = requiredDocument private set - @Column(columnDefinition = "varchar(255)") - var centerName: String = centerName + @Column(columnDefinition = "varchar(255)", nullable = true) + var centerName: String? = centerName private set @Column(columnDefinition = "varchar(255)") var centerAddress: String = centerAddress private set - @Column(columnDefinition = "varchar(255)") - var directUrl: String = directUrl + @Column(columnDefinition = "text", nullable = true) + var directUrl: String? = directUrl private set - @Column(columnDefinition = "varchar(255)") - var createdAt: LocalDateTime = createdAt + @Column(columnDefinition = "timestamp", nullable = true) + var createdAt: LocalDateTime? = createdAt private set - @Column(nullable = false, columnDefinition = "POINT SRID 4326") + @Column(columnDefinition = "POINT SRID 4326") var location: Point = location private set diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/jpa/CrawlingJobPostingJpaRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/jpa/CrawlingJobPostingJpaRepository.kt index f408a9d4..d21c206a 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/jpa/CrawlingJobPostingJpaRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/jpa/CrawlingJobPostingJpaRepository.kt @@ -40,5 +40,4 @@ interface CrawlingJobPostingJpaRepository : JpaRepository? - } diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingFavoriteResponse.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingFavoriteResponse.kt index 3682a99c..0349415f 100644 --- a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingFavoriteResponse.kt +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingFavoriteResponse.kt @@ -20,22 +20,22 @@ data class CrawlingJobPostingFavoriteResponse( val id: UUID, @Schema(description = "공고 제목") - val title: String, + val title: String?, @Schema(description = "근무 시간") - val workingTime: String, + val workingTime: String?, @Schema(description = "근무 스케줄") - val workingSchedule: String, + val workingSchedule: String?, @Schema(description = "급여 정보") - val payInfo: String, + val payInfo: String?, @Schema(description = "공고 모집 마감 기한") - val applyDeadline: String, + val applyDeadline: String?, @Schema(description = "직선 거리", example = "760(단위 : 미터)") - val distance: Int, + val distance: Int?, @get:JsonProperty("isFavorite") @param:JsonProperty("isFavorite") @@ -46,7 +46,7 @@ data class CrawlingJobPostingFavoriteResponse( val jobPostingType: JobPostingType = JobPostingType.WORKNET, @Schema(description = "공고 생성 시각") - val createdAt: LocalDateTime, + val createdAt: LocalDateTime?, ) { companion object { diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt index 9b416b00..b7e2c39b 100644 --- a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt @@ -15,49 +15,49 @@ data class CrawlingJobPostingResponse( val id: UUID, @Schema(description = "모집 요강") - val content: String, + val content: String?, @Schema(description = "고객 주소") - val clientAddress: String, + val clientAddress: String?, @Schema(description = "경도") - val longitude: String, + val longitude: String?, @Schema(description = "위도") - val latitude: String, + val latitude: String?, @Schema(description = "생성 시각") - val createdAt: LocalDateTime, + val createdAt: LocalDateTime?, @Schema(description = "급여 정보") - val payInfo: String, + val payInfo: String?, @Schema(description = "근무 시간") - val workingTime: String, + val workingTime: String?, @Schema(description = "근무 스케줄") - val workingSchedule: String, + val workingSchedule: String?, @Schema(description = "마감 일자") - val applyDeadline: String, + val applyDeadline: String?, @Schema(description = "채용 절차") - val recruitmentProcess: String, + val recruitmentProcess: String?, @Schema(description = "지원 방법") - val applyMethod: String, + val applyMethod: String?, @Schema(description = "필요 서류") - val requiredDocumentation: String, + val requiredDocumentation: String?, @Schema(description = "센터명") - val centerName: String, + val centerName: String?, @Schema(description = "센터 주소") - val centerAddress: String, + val centerAddress: String?, @Schema(description = "외부 공고 url") - val jobPostingUrl: String, + val jobPostingUrl: String?, @get:JsonProperty("isFavorite") @param:JsonProperty("isFavorite") @@ -68,7 +68,7 @@ data class CrawlingJobPostingResponse( val jobPostingType: JobPostingType = JobPostingType.WORKNET, @Schema(description = "거리", example = "700(단위 M)") - val distance: Int, + val distance: Int?, ) { companion object { From e27eed97464978fa116472fc3c20891b74290fc5 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 10 Sep 2024 21:21:00 +0900 Subject: [PATCH 007/108] =?UTF-8?q?[IDLE-365]=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A4=84=EB=9F=AC=20=EA=B8=B0=EC=A4=80=20=EC=8B=9C=EA=B0=81=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index f3a1726a..0b85f9b3 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,7 +13,7 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 0 3 ? * TUE,WED,THU,FRI,SAT") + @Scheduled(cron = "0 0 22 * * *") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) From d34361b3106b916cb46647a3f2e18e73de8ff5ca Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 10 Sep 2024 21:31:58 +0900 Subject: [PATCH 008/108] =?UTF-8?q?[IDLE-365]=20batch=20job=20enable=20?= =?UTF-8?q?=EC=98=B5=EC=85=98=20=EB=B9=84=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idle-batch/src/main/resources/application-batch.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-batch/src/main/resources/application-batch.yml b/idle-batch/src/main/resources/application-batch.yml index 88067df8..4cde540b 100644 --- a/idle-batch/src/main/resources/application-batch.yml +++ b/idle-batch/src/main/resources/application-batch.yml @@ -3,4 +3,4 @@ spring: jdbc: initialize-schema: never job: - enabled: true + enabled: false From dd05abe354203789c4e30de4909e5b20b1a0d53a Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 10 Sep 2024 21:37:57 +0900 Subject: [PATCH 009/108] =?UTF-8?q?[IDLE-365]=20ddl-auto=20update=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idle-domain/src/main/resources/application-domain.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-domain/src/main/resources/application-domain.yml b/idle-domain/src/main/resources/application-domain.yml index c642fdaf..b11c0948 100644 --- a/idle-domain/src/main/resources/application-domain.yml +++ b/idle-domain/src/main/resources/application-domain.yml @@ -31,5 +31,5 @@ spring: on-profile: dev jpa: hibernate: - ddl-auto: create + ddl-auto: update show-sql: false From b6881b00c5e47bb409df38954b535500b6fa6ba1 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 11 Sep 2024 00:33:43 +0900 Subject: [PATCH 010/108] =?UTF-8?q?[IDLE-365]=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=A7=81=20=EA=B3=B5=EA=B3=A0=20=ED=95=84=EB=93=9C=20null=20?= =?UTF-8?q?=EB=B9=84=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/jpa/CrawledJobPosting.kt | 73 +++++++++---------- .../carer/CrawlingJobPostingScrollResponse.kt | 2 +- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt index 45bfff2f..b057b0c0 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt @@ -12,82 +12,81 @@ import java.util.* @Table(name = "crawled_job_posting") class CrawledJobPosting( id: UUID, - title: String?, - content: String?, + title: String, + content: String, clientAddress: String, - payInfo: String?, - workTime: String?, - workSchedule: String?, - applyDeadline: String?, - recruitmentProcess: String?, - applyMethod: String?, - requiredDocument: String?, - centerName: String?, + payInfo: String, + workTime: String, + workSchedule: String, + applyDeadline: String, + recruitmentProcess: String, + applyMethod: String, + requiredDocument: String, + centerName: String, centerAddress: String, - directUrl: String?, - createdAt: LocalDateTime?, + directUrl: String, + createdAt: LocalDateTime, location: Point, ) { @Id - @Column(nullable = true) var id: UUID = id private set - @Column(columnDefinition = "varchar(255)", nullable = true) - var title: String? = title + @Column(columnDefinition = "varchar(255)") + var title: String = title private set - @Column(columnDefinition = "TEXT", nullable = true) - var content: String? = content + @Column(columnDefinition = "TEXT") + var content: String = content private set - @Column(columnDefinition = "varchar(255)", nullable = true) + @Column(columnDefinition = "varchar(255)") var clientAddress: String = clientAddress private set - @Column(columnDefinition = "varchar(255)", nullable = true) - var payInfo: String? = payInfo + @Column(columnDefinition = "varchar(255)") + var payInfo: String = payInfo private set - @Column(columnDefinition = "varchar(255)", nullable = true) - var workTime: String? = workTime + @Column(columnDefinition = "varchar(255)") + var workTime: String = workTime private set - @Column(columnDefinition = "varchar(255)", nullable = true) - var workSchedule: String? = workSchedule + @Column(columnDefinition = "varchar(255)") + var workSchedule: String = workSchedule private set @Column(nullable = true) - var applyDeadline: String? = applyDeadline + var applyDeadline: String = applyDeadline private set - @Column(columnDefinition = "varchar(255)", nullable = true) - var recruitmentProcess: String? = recruitmentProcess + @Column(columnDefinition = "varchar(255)") + var recruitmentProcess: String = recruitmentProcess private set - @Column(columnDefinition = "varchar(255)", nullable = true) - var applyMethod: String? = applyMethod + @Column(columnDefinition = "varchar(255)") + var applyMethod: String = applyMethod private set - @Column(columnDefinition = "varchar(255)", nullable = true) - var requiredDocument: String? = requiredDocument + @Column(columnDefinition = "varchar(255)") + var requiredDocument: String = requiredDocument private set - @Column(columnDefinition = "varchar(255)", nullable = true) - var centerName: String? = centerName + @Column(columnDefinition = "varchar(255)") + var centerName: String = centerName private set @Column(columnDefinition = "varchar(255)") var centerAddress: String = centerAddress private set - @Column(columnDefinition = "text", nullable = true) - var directUrl: String? = directUrl + @Column(columnDefinition = "text") + var directUrl: String = directUrl private set - @Column(columnDefinition = "timestamp", nullable = true) - var createdAt: LocalDateTime? = createdAt + @Column(columnDefinition = "timestamp") + var createdAt: LocalDateTime = createdAt private set @Column(columnDefinition = "POINT SRID 4326") diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingScrollResponse.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingScrollResponse.kt index dd8a5602..e45e368a 100644 --- a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingScrollResponse.kt +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingScrollResponse.kt @@ -63,7 +63,7 @@ data class CrawlingJobPostingScrollResponse( workingTime = crawlingJobPostingPreviewDto.crawledJobPosting.workTime, workingSchedule = crawlingJobPostingPreviewDto.crawledJobPosting.workSchedule, payInfo = crawlingJobPostingPreviewDto.crawledJobPosting.payInfo, - applyDeadline = crawlingJobPostingPreviewDto.crawledJobPosting.applyDeadline.toString(), + applyDeadline = crawlingJobPostingPreviewDto.crawledJobPosting.applyDeadline, distance = crawlingJobPostingPreviewDto.distance, isFavorite = crawlingJobPostingPreviewDto.isFavorite, ) From 470e14cf44a6c83481cdb0cc7386e21083792062 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 11 Sep 2024 00:37:56 +0900 Subject: [PATCH 011/108] =?UTF-8?q?[IDLE-365]=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A4=84=EB=9F=AC=20=EC=8B=9C=EA=B0=84=2002=EC=8B=9C=EB=A1=9C?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index 0b85f9b3..bdebb9fc 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,7 +13,7 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 0 22 * * *") + @Scheduled(cron = "0 0 2 * * *") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) From 1fe565cae250da5ca580ac2432e76226ae0c28fe Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 16 Sep 2024 01:49:51 +0900 Subject: [PATCH 012/108] =?UTF-8?q?[IDLE-366]=20spring=20batch=20selenium?= =?UTF-8?q?=20=ED=81=AC=EB=A1=A4=EB=A7=81=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EB=B9=8C=EB=93=9C=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 30 ++++++++++++++++++++++++++++-- gradle/libs.versions.toml | 2 +- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 98085d88..3b19d2be 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,33 @@ WORKDIR /home/gradle/src RUN gradle :idle-presentation:bootJar --no-daemon # Package stage -FROM openjdk:17 +FROM openjdk:17-slim + +# Install required packages +RUN apt-get update && \ + apt-get install -y \ + wget \ + gnupg \ + curl \ + lsb-release \ + && apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Add the Google Chrome repository and install Chromium and ChromeDriver +RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /usr/share/keyrings/google-archive-keyring.gpg && \ + echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-archive-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | tee /etc/apt/sources.list.d/google-chrome.list && \ + apt-get update && \ + apt-get install -y \ + chromium \ + chromium-driver \ + && apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Set environment variables for Chromium and ChromeDriver +ENV CHROME_BIN=/usr/bin/chromium +ENV CHROMEDRIVER_BIN=/usr/bin/chromedriver + +# Copy the built JAR file COPY --from=build /home/gradle/src/idle-presentation/build/libs/*.jar /app.jar EXPOSE 8080 -ENTRYPOINT ["java","-jar","/app.jar"] +ENTRYPOINT ["java", "-jar", "/app.jar"] diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f6c9d16f..dcfc37ea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -29,7 +29,7 @@ kotlin-logging = "5.1.0" auth0-java-jwt = "4.4.0" auth0-jwks-rsa = "0.22.1" -selenium = "4.23.0" +selenium = "4.24.0" hibernate-spatial = "6.4.4.Final" querydsl = "5.1.0" From 2fced060e61e682ed36d2e9325f2a3c7182ae95e Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 16 Sep 2024 01:50:35 +0900 Subject: [PATCH 013/108] =?UTF-8?q?[IDLE-366]=20worknet=20=EC=82=AC?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=EA=B0=80=20=EA=B3=A0=EC=9A=A9=2024=20?= =?UTF-8?q?=EC=82=AC=EC=9D=B4=ED=8A=B8=EB=A1=9C=20=ED=86=B5=ED=95=A9?= =?UTF-8?q?=EB=90=A8=EC=97=90=20=EB=94=B0=EB=9D=BC,=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=A7=81=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/swm/idle/batch/util/WorknetCrawler.kt | 67 +++++++++++++------ 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt index 209445c6..d5c03414 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt @@ -1,29 +1,59 @@ package com.swm.idle.batch.util import com.swm.idle.batch.common.dto.CrawledJobPostingDto +import io.github.oshai.kotlinlogging.KotlinLogging import org.openqa.selenium.Alert import org.openqa.selenium.By import org.openqa.selenium.NoAlertPresentException import org.openqa.selenium.WebDriver import org.openqa.selenium.chrome.ChromeDriver +import org.openqa.selenium.chrome.ChromeDriverService +import org.openqa.selenium.chrome.ChromeOptions import org.openqa.selenium.support.ui.ExpectedConditions import org.openqa.selenium.support.ui.WebDriverWait +import java.io.File import java.time.Duration import java.time.LocalDate import java.time.format.DateTimeFormatter object WorknetCrawler { + private val logger = KotlinLogging.logger { } + private const val CRAWLING_TARGET_URL_FORMAT = - "https://www.work.go.kr/empInfo/empInfoSrch/list/dtlEmpSrchList.do?careerTo=&keywordJobCd=&occupation=550100%2C550104&templateInfo=&shsyWorkSecd=&rot2WorkYn=&payGbn=&resultCnt=50&keywordJobCont=&cert=&cloDateStdt=&moreCon=&minPay=&codeDepth2Info=11000&isChkLocCall=&sortFieldInfo=DATE&major=&resrDutyExcYn=&eodwYn=&sortField=DATE&staArea=&sortOrderBy=DESC&keyword=&termSearchGbn=D-0&carrEssYns=&benefitSrchAndOr=O&disableEmpHopeGbn=&webIsOut=&actServExcYn=&maxPay=&keywordStaAreaNm=&emailApplyYn=&listCookieInfo=DTL&pageCode=&codeDepth1Info=11000&keywordEtcYn=&publDutyExcYn=&keywordJobCdSeqNo=&exJobsCd=&templateDepthNmInfo=&computerPreferential=®DateStdt={today}&employGbn=&empTpGbcd=®ion=&infaYn=&resultCntInfo=50&siteClcd=WORK%2CP&cloDateEndt=&sortOrderByInfo=DESC&currntPageNo=1&indArea=&careerTypes=&searchOn=Y&tlmgYn=&subEmpHopeYn=&academicGbn=&templateDepthNoInfo=&foriegn=&mealOfferClcd=&station=&moerButtonYn=Y&holidayGbn=&srcKeyword=&enterPriseGbn=all&academicGbnoEdu=noEdu&cloTermSearchGbn=all&keywordWantedTitle=&stationNm=&benefitGbn=&keywordFlag=¬SrcKeyword=&essCertChk=&isEmptyHeader=&depth2SelCode=&_csrf=355cf055-ee67-497a-9695-a65cabc28829&keywordBusiNm=&preferentialGbn=&rot3WorkYn=&pfMatterPreferential=®DateEndt={today}&staAreaLineInfo1=11000&staAreaLineInfo2=1&pageIndex={pageIndex}&termContractMmcnt=&careerFrom=&laborHrShortYn=#viewSPL" + "https://www.work24.go.kr/wk/a/b/1200/retriveDtlEmpSrchList.do?basicSetupYn=&careerTo=&keywordJobCd=&occupation=&seqNo=&cloDateEndtParam=&payGbn=&templateInfo=&rot2WorkYn=&shsyWorkSecd=&srcKeywordParam=%EC%9A%94%EC%96%91%EB%B3%B4%ED%98%B8%EC%82%AC&resultCnt=10&keywordJobCont=&cert=&moreButtonYn=Y&minPay=&codeDepth2Info=11000¤tPageNo=1&eventNo=&mode=&major=&resrDutyExcYn=&eodwYn=&sortField=DATE&staArea=&sortOrderBy=DESC&keyword=%EC%9A%94%EC%96%91%EB%B3%B4%ED%98%B8%EC%82%AC&termSearchGbn=all&carrEssYns=&benefitSrchAndOr=O&disableEmpHopeGbn=&actServExcYn=&keywordStaAreaNm=&maxPay=&emailApplyYn=&codeDepth1Info=11000&keywordEtcYn=®DateStdtParam={today}&publDutyExcYn=&keywordJobCdSeqNo=&viewType=&exJobsCd=&templateDepthNmInfo=®ion=&employGbn=&empTpGbcd=&computerPreferential=&infaYn=&cloDateStdtParam=&siteClcd=WORK&searchMode=Y&birthFromYY=&indArea=&careerTypes=&subEmpHopeYn=&tlmgYn=&academicGbn=&templateDepthNoInfo=&foriegn=&entryRoute=&mealOfferClcd=&basicSetupYnChk=&station=&holidayGbn=&srcKeyword=%EC%9A%94%EC%96%91%EB%B3%B4%ED%98%B8%EC%82%AC&academicGbnoEdu=noEdu&enterPriseGbn=all&cloTermSearchGbn=all&birthToYY=&keywordWantedTitle=&stationNm=&benefitGbn=¬SrcKeywordParam=&keywordFlag=¬SrcKeyword=&essCertChk=&depth2SelCode=&keywordBusiNm=&preferentialGbn=&rot3WorkYn=®DateEndtParam={today}&pfMatterPreferential=&pageIndex={pageIndex}&termContractMmcnt=&careerFrom=&laborHrShortYn=#scrollLoc" private const val JOB_POSTING_COUNT_PER_PAGE = 50 - private val driver: WebDriver = ChromeDriver() + + private lateinit var driver: WebDriver + private val postings = mutableListOf() + private fun initializeDriver() { + val service = ChromeDriverService.Builder() + .usingDriverExecutable(File(System.getenv("CHROMEDRIVER_BIN"))) + .build() + + val options = ChromeOptions().apply { + addArguments("--headless") + addArguments("--no-sandbox") + addArguments("--disable-dev-shm-usage") + addArguments("--disable-gpu") + addArguments("window-size=1920x1080") + addArguments("--disable-software-rasterizer") + addArguments("--ignore-ssl-errors=yes") + addArguments("--ignore-certificate-errors") + + setBinary(System.getenv("CHROME_BIN")) + } + + driver = ChromeDriver(service, options) + } + fun run(): List? { + initializeDriver() + val formatter = DateTimeFormatter.ofPattern("yyyyMMdd") -// val today = LocalDate.now().minusDays(1).format(formatter) val today = LocalDate.now().format(formatter) val crawlingUrl = CRAWLING_TARGET_URL_FORMAT .replace("{today}", today) @@ -31,24 +61,30 @@ object WorknetCrawler { driver.get(crawlingUrl) + val wait = WebDriverWait(driver, Duration.ofSeconds(10)) + wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"mForm\"]/div[2]/div/div[1]/div[1]/span/span"))) + val jobPostingCountText = - driver.findElement(By.xpath("//*[@id=\"srcFrm\"]/div[3]/div[1]/p[2]/em")).text - val jobPostingCount = jobPostingCountText.replace(",", "").toInt() + driver.findElement(By.xpath("//*[@id=\"mForm\"]/div[2]/div/div[1]/div[1]/span/span")).text + val jobPostingCount = Integer.parseInt(jobPostingCountText) if (jobPostingCount == 0) { + driver.quit() return null } val pageCount = jobPostingCount / JOB_POSTING_COUNT_PER_PAGE - for (i in 1..2) { + logger.warn { "pageCount= " + pageCount } + + for (i in 1..pageCount) { if (i >= 2) { val updatedCrawlingUrl = crawlingUrl .replace("{today}", today) .replace(Regex("pageIndex=\\d+"), "pageIndex=${i}") driver.get(updatedCrawlingUrl) } - val wait = WebDriverWait(driver, Duration.ofSeconds(5)) + wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#list1"))) crawlPosts(1, JOB_POSTING_COUNT_PER_PAGE, postings) @@ -62,24 +98,21 @@ object WorknetCrawler { .replace(Regex("pageIndex=\\d+"), "pageIndex=${pageCount + 1}") driver.get(updateCrawlingUrl) - val wait = WebDriverWait(driver, Duration.ofSeconds(5)) wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#list1"))) crawlPosts(1, lastPageJobPostingCount, postings) } driver.quit() - return postings } private fun handleAlertIfPresent() { try { val alert: Alert = driver.switchTo().alert() - println("Alert detected: ${alert.text}") - alert.accept() // Alert 창의 '확인'을 누름 + alert.accept() + driver.navigate().back() } catch (e: NoAlertPresentException) { - // 알림창이 없으면 무시하고 넘어감 } } @@ -92,14 +125,12 @@ object WorknetCrawler { try { val originalWindow = driver.windowHandle - val em = driver.findElement(By.id("list$i")) - val thirdTd = em.findElements(By.tagName("td"))[2] - val jobPostingDetail = thirdTd.findElement(By.cssSelector(".cp-info .cp-info-in a")) - jobPostingDetail.click() + val element = driver.findElement(By.xpath("//*[@id=\"list$i\"]/td[2]/a")) + element.click() handleAlertIfPresent() - val wait = WebDriverWait(driver, Duration.ofSeconds(2)) + val wait = WebDriverWait(driver, Duration.ofSeconds(5)) wait.until(ExpectedConditions.numberOfWindowsToBe(2)) val allWindows = driver.windowHandles @@ -133,7 +164,6 @@ object WorknetCrawler { driver.close() driver.switchTo().window(originalWindow) } catch (e: Exception) { - println("Error crawling job posting $i: ${e.message}") handleAlertIfPresent() } } @@ -231,7 +261,6 @@ object WorknetCrawler { val address = driver.findElement(By.xpath(xpath)).text return address.replace("지도보기", "").trim().replace(Regex("\\(\\d{5}\\)"), "").trim() } catch (e: Exception) { - // Ignore and try the next XPath } } From ccfb321aa834322dbf782f4df1b60d809217113e Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 16 Sep 2024 01:50:57 +0900 Subject: [PATCH 014/108] =?UTF-8?q?[IDLE-366]=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=EB=8F=99=EC=9E=91=20=EC=8A=A4=EC=BC=80=EC=A4=84?= =?UTF-8?q?=EB=A7=81=20=EC=8B=9C=EA=B0=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index bdebb9fc..45d532fe 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,11 +13,12 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 0 2 * * *") + @Scheduled(cron = "0 00 01 * * *") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) .toJobParameters() + jobLauncher.run(crawlingJobConfig.crawlingJob(), jobParameters) } From aafd7c6438b50dfebd1da88987a1a14400346b5a Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 16 Sep 2024 01:52:02 +0900 Subject: [PATCH 015/108] =?UTF-8?q?[IDLE-366]=20=EC=8A=A4=ED=94=84?= =?UTF-8?q?=EB=A7=81=20=EC=B4=88=EA=B8=B0=20=EC=8B=A4=ED=96=89=20=EC=8B=9C?= =?UTF-8?q?,=20spring=20batch=20=EC=9E=90=EB=8F=99=20=EC=8B=A4=ED=96=89=20?= =?UTF-8?q?=EB=B0=A9=EC=A7=80=20=EC=98=B5=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application-batch.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/idle-batch/src/main/resources/application-batch.yml b/idle-batch/src/main/resources/application-batch.yml index 4cde540b..b04610a0 100644 --- a/idle-batch/src/main/resources/application-batch.yml +++ b/idle-batch/src/main/resources/application-batch.yml @@ -2,5 +2,22 @@ spring: batch: jdbc: initialize-schema: never +--- +spring: + config: + activate: + on-profile: local + + batch: + job: + enabled: false +--- +spring: + config: + activate: + on-profile: dev + + batch: job: + name: crawlingJob enabled: false From a5a28fccc480dd7772617be718640c9671476a01 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 16 Sep 2024 01:52:46 +0900 Subject: [PATCH 016/108] =?UTF-8?q?[IDLE-366]=20spring=20batch=205=20?= =?UTF-8?q?=EB=B2=84=EC=A0=84=EC=97=90=EC=84=9C=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EB=90=9C=20=EB=B3=80=EA=B2=BD=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=A0=81=EC=9A=A9=20=EB=B0=8F=20=EB=B3=84=EB=8F=84?= =?UTF-8?q?=EC=9D=98=20JobLauncher=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../idle/batch/common/config/BatchConfig.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/config/BatchConfig.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/config/BatchConfig.kt index ae16bb4b..05a52592 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/config/BatchConfig.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/config/BatchConfig.kt @@ -1,9 +1,43 @@ package com.swm.idle.batch.common.config +import org.springframework.batch.core.explore.JobExplorer +import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.repository.JobRepository +import org.springframework.boot.autoconfigure.batch.BatchProperties +import org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.context.annotation.Bean import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration @Configuration @ComponentScan(basePackages = ["com.swm.idle.batch"]) +@EnableConfigurationProperties(BatchProperties::class) class BatchConfig { + + @Bean + @ConditionalOnMissingBean + @ConditionalOnProperty( + prefix = "spring.batch.job", + name = ["enabled"], + havingValue = "true", + matchIfMissing = true + ) + fun jobLauncherApplicationRunner( + jobLauncher: JobLauncher, + jobExplorer: JobExplorer, + jobRepository: JobRepository, + properties: BatchProperties, + ): JobLauncherApplicationRunner { + val runner = JobLauncherApplicationRunner(jobLauncher, jobExplorer, jobRepository) + val jobName: String? = properties.job.name + + if (!jobName.isNullOrEmpty()) { + runner.setJobName(jobName) + } + + return runner + } } From 3dbc4edf305182cb12bfa3be1e994eb2a8c216de Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 16 Sep 2024 01:53:15 +0900 Subject: [PATCH 017/108] =?UTF-8?q?[IDLE-366]=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EB=B0=8F=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idle-batch/build.gradle.kts | 1 - idle-presentation/compose-dev.yaml | 1 + idle-presentation/src/main/resources/application.yml | 3 --- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/idle-batch/build.gradle.kts b/idle-batch/build.gradle.kts index 61e16818..99582abf 100644 --- a/idle-batch/build.gradle.kts +++ b/idle-batch/build.gradle.kts @@ -14,6 +14,5 @@ dependencies { implementation(rootProject.libs.spring.boot.starter.batch) implementation(rootProject.libs.selenium.java) - implementation(rootProject.libs.selenium.chrome.driver) implementation(libs.mysql.connector.java) } diff --git a/idle-presentation/compose-dev.yaml b/idle-presentation/compose-dev.yaml index 9afb887f..6743589d 100644 --- a/idle-presentation/compose-dev.yaml +++ b/idle-presentation/compose-dev.yaml @@ -14,6 +14,7 @@ services: - mysql ports: - "8080:8080" + mysql: image: mysql:8.0.33 environment: diff --git a/idle-presentation/src/main/resources/application.yml b/idle-presentation/src/main/resources/application.yml index 50ab6650..ffdb983e 100644 --- a/idle-presentation/src/main/resources/application.yml +++ b/idle-presentation/src/main/resources/application.yml @@ -50,9 +50,6 @@ sentry: dsn: ${SENTRY_DSN} environment: dev -logging: - level: - root: WARN --- spring: config: From 94d2c8afb25dfd84aa43c44ef10b3a547c36f495 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 16 Sep 2024 01:53:49 +0900 Subject: [PATCH 018/108] =?UTF-8?q?[IDLE-366]=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=A7=81=20=EC=A1=B0=ED=9A=8C=20API=20=EB=82=B4=20entity=20sta?= =?UTF-8?q?tus=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?=EC=BF=BC=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../idle/batch/job/CrawlingJobPostingTasklet.kt | 15 ++++++++++++--- .../jobposting/entity/jpa/CrawledJobPosting.kt | 7 +++++++ .../jpa/CrawlingJobPostingJpaRepository.kt | 1 + .../querydsl/JobPostingQueryRepository.kt | 1 + 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobPostingTasklet.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobPostingTasklet.kt index a3a0c993..3cc54dbb 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobPostingTasklet.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobPostingTasklet.kt @@ -5,12 +5,12 @@ import com.swm.idle.application.jobposting.domain.CrawlingJobPostingService import com.swm.idle.batch.common.dto.CrawledJobPostingDto import com.swm.idle.batch.util.WorknetCrawler import com.swm.idle.infrastructure.client.geocode.service.GeoCodeService +import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.batch.core.StepContribution import org.springframework.batch.core.scope.context.ChunkContext import org.springframework.batch.core.step.tasklet.Tasklet import org.springframework.batch.repeat.RepeatStatus import org.springframework.stereotype.Component -import org.springframework.transaction.annotation.Transactional @Component class CrawlingJobPostingTasklet( @@ -18,9 +18,18 @@ class CrawlingJobPostingTasklet( private val geoCodeService: GeoCodeService, ) : Tasklet { - @Transactional + private val logger = KotlinLogging.logger { } + override fun execute(contribution: StepContribution, chunkContext: ChunkContext): RepeatStatus { - val crawlingJobPostings: List? = WorknetCrawler.run() + val crawlingJobPostings: List? = try { + WorknetCrawler.run() + } catch (e: Exception) { + logger.warn { + e.toString() + } + e.printStackTrace() // 오류 로그 출력 + null // 오류 발생 + } if (crawlingJobPostings != null) { crawlingJobPostings.mapNotNull { crawledJobPosting -> diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt index b057b0c0..062f7fbd 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt @@ -1,7 +1,10 @@ package com.swm.idle.domain.jobposting.entity.jpa +import com.swm.idle.domain.common.enums.EntityStatus import jakarta.persistence.Column import jakarta.persistence.Entity +import jakarta.persistence.EnumType +import jakarta.persistence.Enumerated import jakarta.persistence.Id import jakarta.persistence.Table import org.locationtech.jts.geom.Point @@ -93,4 +96,8 @@ class CrawledJobPosting( var location: Point = location private set + @Enumerated(EnumType.STRING) + @Column(columnDefinition = "varchar(255)") + var entityStatus: EntityStatus = EntityStatus.ACTIVE + } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/jpa/CrawlingJobPostingJpaRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/jpa/CrawlingJobPostingJpaRepository.kt index d21c206a..7d0a3288 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/jpa/CrawlingJobPostingJpaRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/jpa/CrawlingJobPostingJpaRepository.kt @@ -35,6 +35,7 @@ interface CrawlingJobPostingJpaRepository : JpaRepository Date: Mon, 16 Sep 2024 23:59:21 +0900 Subject: [PATCH 019/108] =?UTF-8?q?[IDLE-358]=20=EC=9A=B4=EC=98=81=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20CD=20=EA=B5=AC=EC=B6=95=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9A=B4=EC=98=81=20=ED=99=98=EA=B2=BD=20profile=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-server-deployer.yaml | 2 +- idle-batch/src/main/resources/application-batch.yml | 11 +++++++++++ idle-domain/src/main/resources/application-domain.yml | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/prod-server-deployer.yaml b/.github/workflows/prod-server-deployer.yaml index 510c0277..f3d1ae53 100644 --- a/.github/workflows/prod-server-deployer.yaml +++ b/.github/workflows/prod-server-deployer.yaml @@ -84,7 +84,7 @@ jobs: sudo docker pull public.ecr.aws/f5q3r6m5/idle-prod-ecr:$IMAGE_TAG sudo docker stop caremeet_server_prod || true sudo docker rm caremeet_server_prod || true - sudo docker run --name caremeet_server_prod --env-file ./.env -d -p 8080:8080 public.ecr.aws/f5q3r6m5/idle-prod-ecr:$IMAGE_TAG + sudo docker run --name caremeet_server_prod --env-file ./app/docker/.env -d -p 8080:8080 public.ecr.aws/f5q3r6m5/idle-prod-ecr:$IMAGE_TAG - name: Remove GitHub Actions IP run: | diff --git a/idle-batch/src/main/resources/application-batch.yml b/idle-batch/src/main/resources/application-batch.yml index b04610a0..ae8cb574 100644 --- a/idle-batch/src/main/resources/application-batch.yml +++ b/idle-batch/src/main/resources/application-batch.yml @@ -21,3 +21,14 @@ spring: job: name: crawlingJob enabled: false +--- +spring: + config: + activate: + on-profile: prod + + batch: + job: + name: crawlingJob + enabled: false + diff --git a/idle-domain/src/main/resources/application-domain.yml b/idle-domain/src/main/resources/application-domain.yml index b11c0948..35a7b5ed 100644 --- a/idle-domain/src/main/resources/application-domain.yml +++ b/idle-domain/src/main/resources/application-domain.yml @@ -31,5 +31,5 @@ spring: on-profile: dev jpa: hibernate: - ddl-auto: update + ddl-auto: validate show-sql: false From 3ce808977ea29bbab57711b9e572a43f4bd5bdd3 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 17 Sep 2024 00:18:03 +0900 Subject: [PATCH 020/108] =?UTF-8?q?[IDLE-358]=20=EC=9A=B4=EC=98=81=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20docker=20run=20=EC=8B=A4=ED=96=89=20?= =?UTF-8?q?=EC=8B=9C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-server-deployer.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/prod-server-deployer.yaml b/.github/workflows/prod-server-deployer.yaml index f3d1ae53..1a75092f 100644 --- a/.github/workflows/prod-server-deployer.yaml +++ b/.github/workflows/prod-server-deployer.yaml @@ -82,8 +82,10 @@ jobs: script: | sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} sudo docker pull public.ecr.aws/f5q3r6m5/idle-prod-ecr:$IMAGE_TAG - sudo docker stop caremeet_server_prod || true - sudo docker rm caremeet_server_prod || true + if [ $(sudo docker ps -q -f name=caremeet_server_prod) ]; then + sudo docker stop caremeet_server_prod + sudo docker rm caremeet_server_prod + fi sudo docker run --name caremeet_server_prod --env-file ./app/docker/.env -d -p 8080:8080 public.ecr.aws/f5q3r6m5/idle-prod-ecr:$IMAGE_TAG - name: Remove GitHub Actions IP From 673462e41e32b3fdb022a55e567143446346744b Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 20 Sep 2024 17:12:41 +0900 Subject: [PATCH 021/108] =?UTF-8?q?[IDLE-000]=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=A7=81=20=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20DTO=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../idle/domain/common/dto/CrawlingJobPostingPreviewDto.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/CrawlingJobPostingPreviewDto.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/CrawlingJobPostingPreviewDto.kt index 9aa851d6..baba6e88 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/CrawlingJobPostingPreviewDto.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/CrawlingJobPostingPreviewDto.kt @@ -12,4 +12,9 @@ data class CrawlingJobPostingPreviewDto( crawledJobPosting: CrawledJobPosting, ) : this(crawledJobPosting = crawledJobPosting, distance = 0, isFavorite = false) + constructor( + crawledJobPosting: CrawledJobPosting, + isFavorite: Boolean, + ) : this(crawledJobPosting = crawledJobPosting, distance = 0, isFavorite = isFavorite) + } From 1ad5d684c3303b7bc97eb7f87172d467733ce66d Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 20 Sep 2024 17:13:23 +0900 Subject: [PATCH 022/108] =?UTF-8?q?[IDLE-000]=20=EA=B3=B5=EA=B3=A0=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20fetchJoin()=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=9D=B4=EC=8A=88=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20subquery=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jobposting/domain/JobPostingService.kt | 10 ++-- .../JobPostingSpatialQueryRepository.kt | 47 ++++++++++--------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingService.kt index 0411681c..cd34f667 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingService.kt @@ -5,12 +5,12 @@ import com.swm.idle.application.jobposting.vo.JobPostingInfo import com.swm.idle.domain.common.dto.JobPostingPreviewDto import com.swm.idle.domain.common.exception.PersistenceException import com.swm.idle.domain.jobposting.entity.jpa.JobPosting -import com.swm.idle.domain.jobposting.repository.jpa.JobPostingJpaRepository -import com.swm.idle.domain.jobposting.repository.querydsl.JobPostingQueryRepository -import com.swm.idle.domain.jobposting.repository.querydsl.JobPostingSpatialQueryRepository import com.swm.idle.domain.jobposting.enums.ApplyDeadlineType import com.swm.idle.domain.jobposting.enums.MentalStatus import com.swm.idle.domain.jobposting.enums.PayType +import com.swm.idle.domain.jobposting.repository.jpa.JobPostingJpaRepository +import com.swm.idle.domain.jobposting.repository.querydsl.JobPostingQueryRepository +import com.swm.idle.domain.jobposting.repository.querydsl.JobPostingSpatialQueryRepository import com.swm.idle.domain.user.common.enum.GenderType import com.swm.idle.domain.user.common.vo.BirthYear import org.locationtech.jts.geom.Point @@ -61,8 +61,8 @@ class JobPostingService( } ?: LocalDate.now().plusMonths(1), applyDeadlineType = jobPostingInfo.applyDeadlineType, location = PointConverter.convertToPoint( - jobPostingInfo.latitude.toDouble(), - jobPostingInfo.longitude.toDouble(), + latitude = jobPostingInfo.latitude.toDouble(), + longitude = jobPostingInfo.longitude.toDouble(), ) ) ).also { diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt index 30927fa9..bfd9d221 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt @@ -1,10 +1,9 @@ package com.swm.idle.domain.jobposting.repository.querydsl -import com.querydsl.core.group.GroupBy.groupBy -import com.querydsl.core.group.GroupBy.list import com.querydsl.core.types.Projections import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.core.types.dsl.Expressions +import com.querydsl.jpa.JPAExpressions import com.querydsl.jpa.impl.JPAQueryFactory import com.swm.idle.domain.applys.entity.jpa.QApplys.applys import com.swm.idle.domain.common.dto.JobPostingPreviewDto @@ -43,29 +42,33 @@ class JobPostingSpatialQueryRepository( return emptyList() } + val applysSub = JPAExpressions + .select(applys.jobPostingId, applys.createdAt) + .from(applys) + .where(applys.jobPostingId.`in`(jobPostingIds)) + + val favoriteSub = JPAExpressions + .select(jobPostingFavorite.jobPostingId) + .from(jobPostingFavorite) + .where( + jobPostingFavorite.jobPostingId.`in`(jobPostingIds) + .and(jobPostingFavorite.entityStatus.eq(EntityStatus.ACTIVE)) + ) + return jpaQueryFactory - .select(jobPosting, jobPostingWeekday, jobPostingFavorite, applys) + .selectDistinct( + Projections.constructor( + JobPostingPreviewDto::class.java, + jobPosting, + jobPostingWeekday, + applysSub, + favoriteSub.exists() + ) + ) .from(jobPosting) - .leftJoin(jobPostingWeekday).fetchJoin() - .on(jobPosting.id.eq(jobPostingWeekday.jobPostingId)) - .leftJoin(applys).fetchJoin() - .on(jobPosting.id.eq(applys.jobPostingId)) - .leftJoin(jobPostingFavorite).fetchJoin() - .on(jobPosting.id.eq(jobPostingFavorite.jobPostingId)) + .leftJoin(jobPostingWeekday).on(jobPosting.id.eq(jobPostingWeekday.jobPostingId)) .where(jobPosting.id.`in`(jobPostingIds)) - .transform( - groupBy(jobPosting.id) - .list( - Projections.constructor( - JobPostingPreviewDto::class.java, - jobPosting, - list(jobPostingWeekday), - applys.createdAt ?: null, - jobPostingFavorite.id.isNotNull - .and(jobPostingFavorite.entityStatus.eq(EntityStatus.ACTIVE)) - ) - ) - ) + .fetch() } private fun isExistInRange( From fddb992b137a3b694de4ad3cfd79d34c10a1714e Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 17 Sep 2024 17:33:27 +0900 Subject: [PATCH 023/108] =?UTF-8?q?[IDLE-000]=20AI=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20coderabbit=20=EB=8F=84=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .coderabbit.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .coderabbit.yaml diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 00000000..3d86ecee --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,14 @@ +language: "ko-KR" +early_access: false +reviews: + profile: "chill" + request_changes_workflow: false + high_level_summary: true + poem: false + review_status: true + collapse_walkthrough: false + auto_review: + enabled: true + drafts: false +chat: + auto_reply: true From 4e7b68fd41b8596b97f3c162239fa8b547c09adf Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 20 Sep 2024 18:05:00 +0900 Subject: [PATCH 024/108] =?UTF-8?q?[IDLE-000]=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=A7=81=20=EA=B3=B5=EA=B3=A0=20=EB=B0=98=EA=B2=BD=EB=B2=94?= =?UTF-8?q?=EC=9C=84=20=EC=A1=B0=ED=9A=8C=20=ED=95=84=ED=84=B0=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20where=EC=A0=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../querydsl/CrawlingJobPostingSpatialQueryRepository.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/CrawlingJobPostingSpatialQueryRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/CrawlingJobPostingSpatialQueryRepository.kt index 9e006f93..43b6f8fe 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/CrawlingJobPostingSpatialQueryRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/CrawlingJobPostingSpatialQueryRepository.kt @@ -23,17 +23,18 @@ class CrawlingJobPostingSpatialQueryRepository( next: UUID?, limit: Long, ): List { - val jobPostingIds = jpaQueryFactory + val crawledJobPostingIds = jpaQueryFactory .select(crawledJobPosting.id) .from(crawledJobPosting) .where( isExistInRange(location) .and(next?.let { crawledJobPosting.id.goe(it) }) + .and(crawledJobPosting.entityStatus.eq(EntityStatus.ACTIVE)) ) .limit(limit) .fetch() - if (jobPostingIds.isEmpty()) { + if (crawledJobPostingIds.isEmpty()) { return emptyList() } @@ -42,6 +43,7 @@ class CrawlingJobPostingSpatialQueryRepository( .from(crawledJobPosting) .leftJoin(jobPostingFavorite).fetchJoin() .on(crawledJobPosting.id.eq(jobPostingFavorite.jobPostingId)) + .where(crawledJobPosting.id.`in`(crawledJobPostingIds)) .transform( groupBy(crawledJobPosting.id) .list( From 270c82649cc6cb736924db83d31ee2af6dfef8da Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 20 Sep 2024 18:22:59 +0900 Subject: [PATCH 025/108] =?UTF-8?q?[IDLE-000]=20TimeZone=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EC=9D=B4=20=EC=A0=81=EC=9A=A9=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/swm/idle/presentation/IdleServerApplication.kt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt index 65d58362..7cb5f7b1 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt @@ -7,7 +7,6 @@ import com.swm.idle.domain.common.config.RedisConfig import com.swm.idle.infrastructure.aws.common.AwsConfig import com.swm.idle.infrastructure.client.common.config.ClientConfig import com.swm.idle.infrastructure.sms.common.config.SmsConfig -import jakarta.annotation.PostConstruct import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication import org.springframework.context.annotation.Import @@ -27,15 +26,11 @@ import java.util.* ) class IdleServerApplication { - @PostConstruct - fun started() { - TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")) - } - companion object { @JvmStatic fun main(args: Array) { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Seoul")) runApplication(*args) } } From 52b36d29e6072ca34cf347e8d5237252ae5dac3e Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 20 Sep 2024 18:42:52 +0900 Subject: [PATCH 026/108] =?UTF-8?q?[IDLE-000]=20TimeZone=20=EC=A7=80?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20@EnableScheduling=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt | 2 +- .../kotlin/com/swm/idle/presentation/IdleServerApplication.kt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index 45d532fe..d94f0ced 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,7 +13,7 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 00 01 * * *") + @Scheduled(cron = "0 00 01 * * *", zone = "KST") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt index 7cb5f7b1..016909b2 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt @@ -10,8 +10,10 @@ import com.swm.idle.infrastructure.sms.common.config.SmsConfig import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication import org.springframework.context.annotation.Import +import org.springframework.scheduling.annotation.EnableScheduling import java.util.* +@EnableScheduling @SpringBootApplication @Import( value = [ From 60e98e59fd29290e64a56ad51a48073190a6b00a Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 20 Sep 2024 21:20:22 +0900 Subject: [PATCH 027/108] =?UTF-8?q?[IDLE-000]=20TimeZone=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index d94f0ced..45d532fe 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,7 +13,7 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 00 01 * * *", zone = "KST") + @Scheduled(cron = "0 00 01 * * *") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) From 26a3899fc474b74c8c8f82d1b8ca93835a99d8ed Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 20 Sep 2024 21:59:48 +0900 Subject: [PATCH 028/108] =?UTF-8?q?[IDLE-000]=20=EA=B3=B5=EA=B3=A0=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20=EC=BF=BC=EB=A6=AC=20?= =?UTF-8?q?=EB=A1=A4=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../JobPostingSpatialQueryRepository.kt | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt index bfd9d221..44ba15c8 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt @@ -1,9 +1,10 @@ package com.swm.idle.domain.jobposting.repository.querydsl +import com.querydsl.core.group.GroupBy.groupBy +import com.querydsl.core.group.GroupBy.list import com.querydsl.core.types.Projections import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.core.types.dsl.Expressions -import com.querydsl.jpa.JPAExpressions import com.querydsl.jpa.impl.JPAQueryFactory import com.swm.idle.domain.applys.entity.jpa.QApplys.applys import com.swm.idle.domain.common.dto.JobPostingPreviewDto @@ -42,33 +43,29 @@ class JobPostingSpatialQueryRepository( return emptyList() } - val applysSub = JPAExpressions - .select(applys.jobPostingId, applys.createdAt) - .from(applys) - .where(applys.jobPostingId.`in`(jobPostingIds)) - - val favoriteSub = JPAExpressions - .select(jobPostingFavorite.jobPostingId) - .from(jobPostingFavorite) - .where( - jobPostingFavorite.jobPostingId.`in`(jobPostingIds) - .and(jobPostingFavorite.entityStatus.eq(EntityStatus.ACTIVE)) - ) - return jpaQueryFactory - .selectDistinct( - Projections.constructor( - JobPostingPreviewDto::class.java, - jobPosting, - jobPostingWeekday, - applysSub, - favoriteSub.exists() - ) - ) + .selectDistinct(jobPosting, jobPostingWeekday, jobPostingFavorite, applys) .from(jobPosting) - .leftJoin(jobPostingWeekday).on(jobPosting.id.eq(jobPostingWeekday.jobPostingId)) + .leftJoin(jobPostingWeekday).fetchJoin() + .on(jobPosting.id.eq(jobPostingWeekday.jobPostingId)) + .leftJoin(applys).fetchJoin() + .on(jobPosting.id.eq(applys.jobPostingId)) + .leftJoin(jobPostingFavorite).fetchJoin() + .on(jobPosting.id.eq(jobPostingFavorite.jobPostingId)) .where(jobPosting.id.`in`(jobPostingIds)) - .fetch() + .transform( + groupBy(jobPosting.id) + .list( + Projections.constructor( + JobPostingPreviewDto::class.java, + jobPosting, + list(jobPostingWeekday), + applys.createdAt ?: null, + jobPostingFavorite.id.isNotNull + .and(jobPostingFavorite.entityStatus.eq(EntityStatus.ACTIVE)) + ) + ) + ) } private fun isExistInRange( From 9eb9f3a400949873601db644cb6c993f9ff79442 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 20 Sep 2024 23:13:34 +0900 Subject: [PATCH 029/108] =?UTF-8?q?[IDLE-000]=20=EA=B8=B0=EC=A1=B4=20?= =?UTF-8?q?=EA=B3=B5=EA=B3=A0=20=EB=82=B4=20location=EC=9D=84=20=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EC=9C=84.=EA=B2=BD=EB=8F=84=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20decoding=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../facade/CrawlingJobPostingFacadeService.kt | 6 ++---- .../jobposting/common/CrawlingJobPostingResponse.kt | 10 +++++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt index e3cdf113..b130de4b 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt @@ -31,8 +31,6 @@ class CrawlingJobPostingFacadeService( val jobPosting = crawlingJobPostingService.getById(crawlingJobPostingId) - val clientLocationInfo = geoCodeService.search(jobPosting.clientAddress) - val distance = crawlingJobPostingService.calculateDistance( jobPosting, PointConverter.convertToPoint( @@ -47,8 +45,8 @@ class CrawlingJobPostingFacadeService( CrawlingJobPostingResponse.from( crawlingJobPosting = it, - longitude = clientLocationInfo.addresses[0].x, - latitude = clientLocationInfo.addresses[0].y, + longitude = jobPosting.location.x, + latitude = jobPosting.location.y, isFavorite = isFavorite, distance = distance, ) diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt index b7e2c39b..7c18b606 100644 --- a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt @@ -75,8 +75,8 @@ data class CrawlingJobPostingResponse( fun from( crawlingJobPosting: CrawledJobPosting, - longitude: String, - latitude: String, + longitude: Double, + latitude: Double, isFavorite: Boolean, distance: Int, ): CrawlingJobPostingResponse { @@ -84,13 +84,13 @@ data class CrawlingJobPostingResponse( id = crawlingJobPosting.id, content = crawlingJobPosting.content, clientAddress = crawlingJobPosting.clientAddress, - longitude = longitude, - latitude = latitude, + longitude = longitude.toString(), + latitude = latitude.toString(), createdAt = crawlingJobPosting.createdAt, payInfo = crawlingJobPosting.payInfo, workingTime = crawlingJobPosting.workTime, workingSchedule = crawlingJobPosting.workSchedule, - applyDeadline = crawlingJobPosting.applyDeadline.toString(), + applyDeadline = crawlingJobPosting.applyDeadline, recruitmentProcess = crawlingJobPosting.recruitmentProcess, applyMethod = crawlingJobPosting.applyMethod, requiredDocumentation = crawlingJobPosting.requiredDocument, From 11c254deada3f3955332b5ebcc4c9b6b10b6cdcc Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Sun, 22 Sep 2024 16:51:16 +0900 Subject: [PATCH 030/108] =?UTF-8?q?[IDLE-000]=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=EC=A0=84=20=EC=B5=9C=EC=A2=85=20QA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jobposting/domain/JobPostingService.kt | 3 ++ .../facade/CarerJobPostingFacadeService.kt | 19 +++++++----- .../batch/common/dto/CrawledJobPostingDto.kt | 8 ++--- .../swm/idle/batch/job/CrawlingJobConfig.kt | 1 + .../domain/common/dto/JobPostingPreviewDto.kt | 8 ++--- .../entity/jpa/CrawledJobPosting.kt | 6 ++-- .../querydsl/JobPostingQueryRepository.kt | 6 ++-- .../JobPostingSpatialQueryRepository.kt | 30 ++++++++++++++----- .../CrawlingJobPostingFavoriteResponse.kt | 6 ++-- .../common/CrawlingJobPostingResponse.kt | 8 +++-- 10 files changed, 60 insertions(+), 35 deletions(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingService.kt index cd34f667..a8aefb31 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingService.kt @@ -11,6 +11,7 @@ import com.swm.idle.domain.jobposting.enums.PayType import com.swm.idle.domain.jobposting.repository.jpa.JobPostingJpaRepository import com.swm.idle.domain.jobposting.repository.querydsl.JobPostingQueryRepository import com.swm.idle.domain.jobposting.repository.querydsl.JobPostingSpatialQueryRepository +import com.swm.idle.domain.user.carer.entity.jpa.Carer import com.swm.idle.domain.user.common.enum.GenderType import com.swm.idle.domain.user.common.vo.BirthYear import org.locationtech.jts.geom.Point @@ -194,11 +195,13 @@ class JobPostingService( } fun findAllByCarerLocationInRange( + carer: Carer, location: Point, next: UUID?, limit: Long, ): List { return jobPostingSpatialQueryRepository.findAllWithWeekdaysInRange( + carer = carer, location = location, next = next, limit = limit, diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CarerJobPostingFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CarerJobPostingFacadeService.kt index 7a10ec5c..a23613bb 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CarerJobPostingFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CarerJobPostingFacadeService.kt @@ -101,20 +101,23 @@ class CarerJobPostingFacadeService( next: UUID?, limit: Long, ): Pair, UUID?> { + val carer = getUserAuthentication().userId.let { + carerService.getById(it) + } + val jobPostingPreviewDtos = jobPostingService.findAllByCarerLocationInRange( + carer = carer, location = location, next = next, limit = limit + 1, ) - val carerLocation = getUserAuthentication().userId.let { - carerService.getById(it) - }.let { - PointConverter.convertToPoint( - latitude = it.latitude.toDouble(), - longitude = it.longitude.toDouble(), - ) - } + + val carerLocation = PointConverter.convertToPoint( + latitude = carer.latitude.toDouble(), + longitude = carer.longitude.toDouble(), + ) + for (jobPostingPreviewDto in jobPostingPreviewDtos) { jobPostingPreviewDto.distance = jobPostingService.calculateDistance( diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/dto/CrawledJobPostingDto.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/dto/CrawledJobPostingDto.kt index 69955c74..60b6eff2 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/dto/CrawledJobPostingDto.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/dto/CrawledJobPostingDto.kt @@ -3,7 +3,7 @@ package com.swm.idle.batch.common.dto import com.swm.idle.domain.jobposting.entity.jpa.CrawledJobPosting import com.swm.idle.support.common.uuid.UuidCreator import org.locationtech.jts.geom.Point -import java.time.LocalDateTime +import java.time.LocalDate import java.time.format.DateTimeFormatter data class CrawledJobPostingDto( @@ -29,9 +29,9 @@ data class CrawledJobPostingDto( title = title, content = content, clientAddress = clientAddress, - createdAt = LocalDateTime.parse( - createdAt, - DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss") + createdAt = LocalDate.parse( + createdAt.substring(0, 10), + DateTimeFormatter.ofPattern("yyyy.MM.dd") ), payInfo = payInfo, workTime = workTime, diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobConfig.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobConfig.kt index 772ae67c..7b6e8258 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobConfig.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/job/CrawlingJobConfig.kt @@ -27,6 +27,7 @@ class CrawlingJobConfig( fun crawlingJobPostStep(): Step { return StepBuilder("crawlingJobPostStep", jobRepository) .tasklet(crawlingJobPostingTasklet, transactionManager) + .allowStartIfComplete(true) .build() } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/JobPostingPreviewDto.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/JobPostingPreviewDto.kt index cf08fc8f..792af056 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/JobPostingPreviewDto.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/JobPostingPreviewDto.kt @@ -14,15 +14,15 @@ data class JobPostingPreviewDto( constructor( jobPosting: JobPosting, - jobPostingWeekdays: List, + jobPostingWeekdays: Set, applyTime: LocalDateTime?, - ) : this(jobPosting, jobPostingWeekdays, 0, applyTime, true) + ) : this(jobPosting, jobPostingWeekdays.toList(), 0, applyTime, true) constructor( jobPosting: JobPosting, - jobPostingWeekdays: List, + jobPostingWeekdays: Set, applyTime: LocalDateTime?, isFavorite: Boolean, - ) : this(jobPosting, jobPostingWeekdays, 0, applyTime, isFavorite) + ) : this(jobPosting, jobPostingWeekdays.toList(), 0, applyTime, isFavorite) } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt index 062f7fbd..9ea7a711 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt @@ -8,7 +8,7 @@ import jakarta.persistence.Enumerated import jakarta.persistence.Id import jakarta.persistence.Table import org.locationtech.jts.geom.Point -import java.time.LocalDateTime +import java.time.LocalDate import java.util.* @Entity @@ -28,7 +28,7 @@ class CrawledJobPosting( centerName: String, centerAddress: String, directUrl: String, - createdAt: LocalDateTime, + createdAt: LocalDate, location: Point, ) { @@ -89,7 +89,7 @@ class CrawledJobPosting( private set @Column(columnDefinition = "timestamp") - var createdAt: LocalDateTime = createdAt + var createdAt: LocalDate = createdAt private set @Column(columnDefinition = "POINT SRID 4326") diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingQueryRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingQueryRepository.kt index 99a98f98..e5068445 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingQueryRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingQueryRepository.kt @@ -1,7 +1,7 @@ package com.swm.idle.domain.jobposting.repository.querydsl import com.querydsl.core.group.GroupBy.groupBy -import com.querydsl.core.group.GroupBy.list +import com.querydsl.core.group.GroupBy.set import com.querydsl.core.types.Projections import com.querydsl.jpa.impl.JPAQueryFactory import com.swm.idle.domain.applys.entity.jpa.QApplys.applys @@ -54,7 +54,7 @@ class JobPostingQueryRepository( Projections.constructor( JobPostingPreviewDto::class.java, jobPosting, - list(jobPostingWeekday), + set(jobPostingWeekday), applys.createdAt, jobPostingFavorite.id.isNotNull .and(jobPostingFavorite.entityStatus.eq(EntityStatus.ACTIVE)) @@ -83,7 +83,7 @@ class JobPostingQueryRepository( Projections.constructor( JobPostingPreviewDto::class.java, jobPosting, - list(jobPostingWeekday), + set(jobPostingWeekday), applys.createdAt ?: null, ) ) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt index 44ba15c8..7f824007 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt @@ -1,7 +1,7 @@ package com.swm.idle.domain.jobposting.repository.querydsl import com.querydsl.core.group.GroupBy.groupBy -import com.querydsl.core.group.GroupBy.list +import com.querydsl.core.group.GroupBy.set import com.querydsl.core.types.Projections import com.querydsl.core.types.dsl.BooleanExpression import com.querydsl.core.types.dsl.Expressions @@ -13,6 +13,7 @@ import com.swm.idle.domain.jobposting.entity.jpa.QJobPosting.jobPosting import com.swm.idle.domain.jobposting.entity.jpa.QJobPostingFavorite.jobPostingFavorite import com.swm.idle.domain.jobposting.entity.jpa.QJobPostingWeekday.jobPostingWeekday import com.swm.idle.domain.jobposting.enums.JobPostingStatus +import com.swm.idle.domain.user.carer.entity.jpa.Carer import org.locationtech.jts.geom.Point import org.springframework.stereotype.Repository import java.util.* @@ -23,6 +24,7 @@ class JobPostingSpatialQueryRepository( ) { fun findAllWithWeekdaysInRange( + carer: Carer, location: Point, next: UUID?, limit: Long, @@ -44,12 +46,20 @@ class JobPostingSpatialQueryRepository( } return jpaQueryFactory - .selectDistinct(jobPosting, jobPostingWeekday, jobPostingFavorite, applys) + .selectDistinct( + jobPosting, + jobPostingWeekday, + applys, + jobPostingFavorite + ) .from(jobPosting) - .leftJoin(jobPostingWeekday).fetchJoin() + .innerJoin(jobPostingWeekday) .on(jobPosting.id.eq(jobPostingWeekday.jobPostingId)) - .leftJoin(applys).fetchJoin() - .on(jobPosting.id.eq(applys.jobPostingId)) + .leftJoin(applys) + .on( + jobPosting.id.eq(applys.jobPostingId) + .and(applys.carerId.eq(carer.id)) + ) .leftJoin(jobPostingFavorite).fetchJoin() .on(jobPosting.id.eq(jobPostingFavorite.jobPostingId)) .where(jobPosting.id.`in`(jobPostingIds)) @@ -59,10 +69,14 @@ class JobPostingSpatialQueryRepository( Projections.constructor( JobPostingPreviewDto::class.java, jobPosting, - list(jobPostingWeekday), + set(jobPostingWeekday), applys.createdAt ?: null, - jobPostingFavorite.id.isNotNull - .and(jobPostingFavorite.entityStatus.eq(EntityStatus.ACTIVE)) + Expressions.booleanTemplate( + "case when {0} is not null and {1} = {2} then true else false end", + jobPostingFavorite.id, + jobPostingFavorite.entityStatus, + EntityStatus.ACTIVE + ) ) ) ) diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingFavoriteResponse.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingFavoriteResponse.kt index 0349415f..6e3e6b7b 100644 --- a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingFavoriteResponse.kt +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CrawlingJobPostingFavoriteResponse.kt @@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.swm.idle.domain.jobposting.entity.jpa.CrawledJobPosting import com.swm.idle.domain.jobposting.enums.JobPostingType import io.swagger.v3.oas.annotations.media.Schema -import java.time.LocalDateTime +import java.time.LocalDate import java.util.* @Schema( @@ -46,7 +46,7 @@ data class CrawlingJobPostingFavoriteResponse( val jobPostingType: JobPostingType = JobPostingType.WORKNET, @Schema(description = "공고 생성 시각") - val createdAt: LocalDateTime?, + val createdAt: LocalDate?, ) { companion object { @@ -61,7 +61,7 @@ data class CrawlingJobPostingFavoriteResponse( workingTime = crawledJobPosting.workTime, workingSchedule = crawledJobPosting.workSchedule, payInfo = crawledJobPosting.payInfo, - applyDeadline = crawledJobPosting.applyDeadline.toString(), + applyDeadline = crawledJobPosting.applyDeadline, distance = distance, isFavorite = true, createdAt = crawledJobPosting.createdAt, diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt index 7c18b606..766e190c 100644 --- a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/common/CrawlingJobPostingResponse.kt @@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.swm.idle.domain.jobposting.entity.jpa.CrawledJobPosting import com.swm.idle.domain.jobposting.enums.JobPostingType import io.swagger.v3.oas.annotations.media.Schema -import java.time.LocalDateTime +import java.time.LocalDate import java.util.* @Schema( @@ -14,6 +14,9 @@ import java.util.* data class CrawlingJobPostingResponse( val id: UUID, + @Schema(description = "공고 제목") + val title: String?, + @Schema(description = "모집 요강") val content: String?, @@ -27,7 +30,7 @@ data class CrawlingJobPostingResponse( val latitude: String?, @Schema(description = "생성 시각") - val createdAt: LocalDateTime?, + val createdAt: LocalDate?, @Schema(description = "급여 정보") val payInfo: String?, @@ -82,6 +85,7 @@ data class CrawlingJobPostingResponse( ): CrawlingJobPostingResponse { return CrawlingJobPostingResponse( id = crawlingJobPosting.id, + title = crawlingJobPosting.title, content = crawlingJobPosting.content, clientAddress = crawlingJobPosting.clientAddress, longitude = longitude.toString(), From d6ee04e5abcafffa3b84e8549f39c64aec25154a Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Sun, 22 Sep 2024 17:02:10 +0900 Subject: [PATCH 031/108] =?UTF-8?q?[IDLE-000]=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=A7=81=20=EA=B3=B5=EA=B3=A0=20=EC=83=9D=EC=84=B1=EC=9D=BC?= =?UTF-8?q?=EC=9E=90=20=ED=95=84=EB=93=9C=20type=20=EB=B3=80=EA=B2=BD(time?= =?UTF-8?q?stamp=20->=20date)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt index 9ea7a711..52d2b1f9 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/entity/jpa/CrawledJobPosting.kt @@ -88,7 +88,7 @@ class CrawledJobPosting( var directUrl: String = directUrl private set - @Column(columnDefinition = "timestamp") + @Column(columnDefinition = "date") var createdAt: LocalDate = createdAt private set From 9cbfe6369b0190716c17af51bb78cd7934069253 Mon Sep 17 00:00:00 2001 From: Wonjun You <59856002+wonjunYou@users.noreply.github.com> Date: Tue, 24 Sep 2024 20:29:16 +0900 Subject: [PATCH 032/108] =?UTF-8?q?[IDLE-000]=20Redis=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#171)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [IDLE-000] Redis 비밀번호 설정 추가 * [IDLE-000] yaml 파일에 password 필드 추가 * [IDLE-000] redis local default password 설정 * [IDLE-000] compose 파일 내, 비밀번호 지정 command 설정 --- .../com/swm/idle/domain/common/config/RedisConfig.kt | 10 +++++++++- .../idle/domain/common/properties/RedisProperties.kt | 1 + idle-domain/src/main/resources/application-domain.yml | 1 + idle-presentation/compose-dev.yaml | 3 +++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/config/RedisConfig.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/config/RedisConfig.kt index 744ca73d..25c63038 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/config/RedisConfig.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/config/RedisConfig.kt @@ -5,6 +5,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.data.redis.connection.RedisConnectionFactory +import org.springframework.data.redis.connection.RedisPassword +import org.springframework.data.redis.connection.RedisStandaloneConfiguration import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory import org.springframework.data.redis.core.RedisTemplate import org.springframework.data.redis.repository.configuration.EnableRedisRepositories @@ -18,7 +20,13 @@ class RedisConfig( @Bean fun connectionFactory(): RedisConnectionFactory { - return LettuceConnectionFactory(redisProperties.host, redisProperties.port) + RedisStandaloneConfiguration().apply { + hostName = redisProperties.host + port = redisProperties.port + password = RedisPassword.of(redisProperties.password) + }.also { + return LettuceConnectionFactory(it) + } } @Bean diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/properties/RedisProperties.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/properties/RedisProperties.kt index 7421721a..ea177346 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/properties/RedisProperties.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/properties/RedisProperties.kt @@ -6,4 +6,5 @@ import org.springframework.boot.context.properties.ConfigurationProperties data class RedisProperties( val host: String, val port: Int, + val password: String, ) diff --git a/idle-domain/src/main/resources/application-domain.yml b/idle-domain/src/main/resources/application-domain.yml index 35a7b5ed..73b540fd 100644 --- a/idle-domain/src/main/resources/application-domain.yml +++ b/idle-domain/src/main/resources/application-domain.yml @@ -13,6 +13,7 @@ spring: redis: host: ${REDIS_HOST:localhost} port: ${REDIS_PORT:6379} + password: ${REDIS_PASSWORD:redis} --- spring: config: diff --git a/idle-presentation/compose-dev.yaml b/idle-presentation/compose-dev.yaml index 6743589d..71c5b133 100644 --- a/idle-presentation/compose-dev.yaml +++ b/idle-presentation/compose-dev.yaml @@ -29,6 +29,9 @@ services: container_name: redis_dev ports: - "6379:6379" + environment: + REDIS_PASSWORD: ${REDIS_PASSWORD} + command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"] volumes: mysql-volume: From 150168b8bca7251a826373474a951c3a5ee59fe4 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 24 Sep 2024 21:17:29 +0900 Subject: [PATCH 033/108] =?UTF-8?q?[IDLE-000]=20Redis=20=EB=B3=BC=EB=A5=A8?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idle-presentation/compose-dev.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/idle-presentation/compose-dev.yaml b/idle-presentation/compose-dev.yaml index 71c5b133..a54a7261 100644 --- a/idle-presentation/compose-dev.yaml +++ b/idle-presentation/compose-dev.yaml @@ -31,7 +31,11 @@ services: - "6379:6379" environment: REDIS_PASSWORD: ${REDIS_PASSWORD} - command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"] + command: [ "redis-server", "--requirepass", "$REDIS_PASSWORD" ] + volumes: + - redis-volume:/data + restart: unless-stopped volumes: mysql-volume: + redis-volume: From 599bbd156f7df60b01355cbc80d3cf5cff71ddcb Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 24 Sep 2024 21:19:36 +0900 Subject: [PATCH 034/108] =?UTF-8?q?[IDLE-000]=20ci=20triggering=20branch?= =?UTF-8?q?=20=EC=9E=84=EC=8B=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-integrator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-integrator.yaml b/.github/workflows/dev-server-integrator.yaml index 0cf1cc65..bd19d3a3 100644 --- a/.github/workflows/dev-server-integrator.yaml +++ b/.github/workflows/dev-server-integrator.yaml @@ -3,7 +3,7 @@ name: Develop Server Integrator (CI) on: push: branches: - - develop + - chore/IDLE-000 jobs: build_and_push: From 31d881b6322234d8bbbcbc85d62a79a0317ddb86 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 24 Sep 2024 21:56:10 +0900 Subject: [PATCH 035/108] =?UTF-8?q?[IDLE-000]=20ci=20triggering=20branch?= =?UTF-8?q?=20=EB=A1=A4=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-integrator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-integrator.yaml b/.github/workflows/dev-server-integrator.yaml index bd19d3a3..0cf1cc65 100644 --- a/.github/workflows/dev-server-integrator.yaml +++ b/.github/workflows/dev-server-integrator.yaml @@ -3,7 +3,7 @@ name: Develop Server Integrator (CI) on: push: branches: - - chore/IDLE-000 + - develop jobs: build_and_push: From 3873a8ed75a4c8245044a3dde181d56e3b386b69 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 25 Sep 2024 13:14:34 +0900 Subject: [PATCH 036/108] =?UTF-8?q?[IDLE-000]=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=8B=AC=EC=82=AC=20=ED=86=B5=EA=B3=BC=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=A0=84=ED=99=94=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/common/service/facade/AuthFacadeService.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/facade/AuthFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/facade/AuthFacadeService.kt index 806253bb..abff6099 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/facade/AuthFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/facade/AuthFacadeService.kt @@ -43,6 +43,11 @@ class AuthFacadeService( phoneNumber: PhoneNumber, verificationNumber: UserPhoneVerificationNumber, ) { + // 앱 심사 통과를 위한 임시 로직 + if (phoneNumber.value.equals("010-1234-5678")) { + return + } + userPhoneVerificationService.findByPhoneNumber(phoneNumber)?.let { if (it.first != phoneNumber || it.second != verificationNumber) { throw UserException.InvalidVerificationNumber() From 38a027af91cb862a4af8b5ff3cd5d138b525ad75 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 25 Sep 2024 14:11:14 +0900 Subject: [PATCH 037/108] =?UTF-8?q?[IDLE-000]=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=8B=AC=EC=82=AC=20=ED=86=B5=EA=B3=BC=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=A0=84=ED=99=94=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/carer/facade/CarerAuthFacadeService.kt | 12 +++++++----- .../user/common/service/facade/AuthFacadeService.kt | 5 ----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/carer/facade/CarerAuthFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/carer/facade/CarerAuthFacadeService.kt index 81caf5fc..f4bc8025 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/user/carer/facade/CarerAuthFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/carer/facade/CarerAuthFacadeService.kt @@ -63,11 +63,13 @@ class CarerAuthFacadeService( phoneNumber: PhoneNumber, verificationNumber: UserPhoneVerificationNumber, ): LoginResponse { - userPhoneVerificationService.findByPhoneNumber(phoneNumber)?.let { - if (it.first != phoneNumber || it.second != verificationNumber) { - throw UserException.InvalidVerificationNumber() - } - } ?: throw UserException.VerificationNumberNotFound() + if (phoneNumber.value.equals("010-1234-5678").not()) { + userPhoneVerificationService.findByPhoneNumber(phoneNumber)?.let { + if (it.first != phoneNumber || it.second != verificationNumber) { + throw UserException.InvalidVerificationNumber() + } + } ?: throw UserException.VerificationNumberNotFound() + } val carer = carerService.findByPhoneNumber(phoneNumber) ?: throw SecurityException.UnregisteredUser() diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/facade/AuthFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/facade/AuthFacadeService.kt index abff6099..806253bb 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/facade/AuthFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/common/service/facade/AuthFacadeService.kt @@ -43,11 +43,6 @@ class AuthFacadeService( phoneNumber: PhoneNumber, verificationNumber: UserPhoneVerificationNumber, ) { - // 앱 심사 통과를 위한 임시 로직 - if (phoneNumber.value.equals("010-1234-5678")) { - return - } - userPhoneVerificationService.findByPhoneNumber(phoneNumber)?.let { if (it.first != phoneNumber || it.second != verificationNumber) { throw UserException.InvalidVerificationNumber() From bb56bb35a0231c001c815bc70cd995de8c87b794 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 23 Sep 2024 17:38:04 +0900 Subject: [PATCH 038/108] =?UTF-8?q?[IDLE-389]=20=EC=84=BC=ED=84=B0=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=9A=94=EC=B2=AD=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=B0=9C=EC=83=9D=20=EC=8B=9C,=20=EB=94=94?= =?UTF-8?q?=EC=8A=A4=EC=BD=94=EB=93=9C=20=EC=9B=B9=ED=9B=85=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=EC=9D=84=20=EC=A0=84=EC=86=A1=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/CenterManagerEventPublisher.kt | 16 ++++++++ .../service/facade/CenterAuthFacadeService.kt | 12 ++++-- .../user/center/entity/jpa/CenterManager.kt | 4 ++ .../center/event/CenterManagerVerifyEvent.kt | 19 +++++++++ .../client/discord/common/event/EventType.kt | 5 +++ .../properties/DiscordClientProperties.kt | 15 +++++++ .../common/utils/DiscordMessageClient.kt | 23 +++++++++++ .../discord/common/vo/DiscordMessage.kt | 5 +++ .../listener/CenterManagerEventListener.kt | 18 +++++++++ .../CenterManagerVerifyEventService.kt | 39 +++++++++++++++++++ .../src/main/resources/application-client.yml | 18 +++++++++ 11 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerEventPublisher.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/event/CenterManagerVerifyEvent.kt create mode 100644 idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/event/EventType.kt create mode 100644 idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/properties/DiscordClientProperties.kt create mode 100644 idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/utils/DiscordMessageClient.kt create mode 100644 idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/vo/DiscordMessage.kt create mode 100644 idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/listener/CenterManagerEventListener.kt create mode 100644 idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/service/CenterManagerVerifyEventService.kt diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerEventPublisher.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerEventPublisher.kt new file mode 100644 index 00000000..f8fe19e1 --- /dev/null +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerEventPublisher.kt @@ -0,0 +1,16 @@ +package com.swm.idle.application.user.center.service.domain + +import com.swm.idle.domain.user.center.event.CenterManagerVerifyEvent +import org.springframework.context.ApplicationEventPublisher +import org.springframework.stereotype.Service + +@Service +class CenterManagerEventPublisher( + private val eventPublisher: ApplicationEventPublisher, +) { + + fun publish(centerManagerVerifyEvent: CenterManagerVerifyEvent) { + eventPublisher.publishEvent(centerManagerVerifyEvent) + } + +} diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt index 63b75316..9705cc88 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt @@ -1,12 +1,14 @@ package com.swm.idle.application.user.center.service.facade import com.swm.idle.application.common.security.getUserAuthentication +import com.swm.idle.application.user.center.service.domain.CenterManagerEventPublisher import com.swm.idle.application.user.center.service.domain.CenterManagerService import com.swm.idle.application.user.common.service.domain.DeletedUserInfoService import com.swm.idle.application.user.common.service.domain.RefreshTokenService import com.swm.idle.application.user.common.service.util.JwtTokenService import com.swm.idle.domain.common.enums.EntityStatus import com.swm.idle.domain.common.exception.PersistenceException +import com.swm.idle.domain.user.center.event.CenterManagerVerifyEvent.Companion.createVerifyEvent import com.swm.idle.domain.user.center.exception.CenterException import com.swm.idle.domain.user.center.vo.BusinessRegistrationNumber import com.swm.idle.domain.user.center.vo.Identifier @@ -30,6 +32,7 @@ class CenterAuthFacadeService( private val deletedUserInfoService: DeletedUserInfoService, private val jwtTokenService: JwtTokenService, private val refreshTokenService: RefreshTokenService, + private val centerManagerEventPublisher: CenterManagerEventPublisher, ) { fun join( @@ -138,10 +141,13 @@ class CenterAuthFacadeService( @Transactional fun requestCenterManagerVerification() { - getUserAuthentication().userId + val centerManager = getUserAuthentication().userId .let { centerManagerService.getById(it) } - .takeIf { it.entityStatus == EntityStatus.ACTIVE } - ?.let { centerManagerService.updateAccountStatusToPending(it) } + + if (centerManager.entityStatus == EntityStatus.ACTIVE && centerManager.isNew()) { + centerManagerEventPublisher.publish(centerManager.createVerifyEvent()) + centerManagerService.updateAccountStatusToPending(centerManager) + } } } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/entity/jpa/CenterManager.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/entity/jpa/CenterManager.kt index ca9c83ec..f4619f61 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/entity/jpa/CenterManager.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/entity/jpa/CenterManager.kt @@ -44,4 +44,8 @@ class CenterManager( this.status = CenterManagerAccountStatus.PENDING } + fun isNew(): Boolean { + return status == CenterManagerAccountStatus.NEW + } + } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/event/CenterManagerVerifyEvent.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/event/CenterManagerVerifyEvent.kt new file mode 100644 index 00000000..8554f5e9 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/event/CenterManagerVerifyEvent.kt @@ -0,0 +1,19 @@ +package com.swm.idle.domain.user.center.event + +import com.swm.idle.domain.user.center.entity.jpa.CenterManager + +data class CenterManagerVerifyEvent( + val centerManager: CenterManager, +) { + + companion object { + + fun CenterManager.createVerifyEvent(): CenterManagerVerifyEvent { + require(isNew()) { "인증 요청이 가능한 상태가 아닙니다." } + + return CenterManagerVerifyEvent(this) + } + + } + +} diff --git a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/event/EventType.kt b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/event/EventType.kt new file mode 100644 index 00000000..37c912d0 --- /dev/null +++ b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/event/EventType.kt @@ -0,0 +1,5 @@ +package com.swm.idle.infrastructure.client.discord.common.event + +enum class EventType { + CENTER_MANAGER_VERIFICATION, +} diff --git a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/properties/DiscordClientProperties.kt b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/properties/DiscordClientProperties.kt new file mode 100644 index 00000000..03334a52 --- /dev/null +++ b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/properties/DiscordClientProperties.kt @@ -0,0 +1,15 @@ +package com.swm.idle.infrastructure.client.discord.common.properties + +import com.swm.idle.infrastructure.client.discord.common.event.EventType +import org.springframework.boot.context.properties.ConfigurationProperties + +@ConfigurationProperties("client") +class DiscordClientProperties( + val events: Map, +) { + + data class Properties( + val active: Boolean, + val url: String, + ) +} diff --git a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/utils/DiscordMessageClient.kt b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/utils/DiscordMessageClient.kt new file mode 100644 index 00000000..29d8f5e4 --- /dev/null +++ b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/utils/DiscordMessageClient.kt @@ -0,0 +1,23 @@ +package com.swm.idle.infrastructure.client.discord.common.utils + +import com.swm.idle.infrastructure.client.discord.common.vo.DiscordMessage +import org.springframework.cloud.openfeign.FeignClient +import org.springframework.http.MediaType +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import java.net.URI + +@FeignClient( + name = "discord-message-client", + url = "discord-webhook-url" +) +fun interface DiscordMessageClient { + + @PostMapping(consumes = [MediaType.APPLICATION_JSON_VALUE]) + fun send( + uri: URI, + @RequestBody + message: DiscordMessage, + ) + +} diff --git a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/vo/DiscordMessage.kt b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/vo/DiscordMessage.kt new file mode 100644 index 00000000..2f30cc55 --- /dev/null +++ b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/common/vo/DiscordMessage.kt @@ -0,0 +1,5 @@ +package com.swm.idle.infrastructure.client.discord.common.vo + +data class DiscordMessage( + val content: String, +) diff --git a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/listener/CenterManagerEventListener.kt b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/listener/CenterManagerEventListener.kt new file mode 100644 index 00000000..ac6d8e14 --- /dev/null +++ b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/listener/CenterManagerEventListener.kt @@ -0,0 +1,18 @@ +package com.swm.idle.infrastructure.client.discord.user.center.listener + +import com.swm.idle.domain.user.center.event.CenterManagerVerifyEvent +import com.swm.idle.infrastructure.client.discord.user.center.service.CenterManagerVerifyEventService +import org.springframework.context.event.EventListener +import org.springframework.stereotype.Component + +@Component +class CenterManagerEventListener( + private val centerMangerVerifyEventService: CenterManagerVerifyEventService, +) { + + @EventListener + fun handleCenterManagerVerifyEvent(centerManagerVerifyEvent: CenterManagerVerifyEvent) { + centerMangerVerifyEventService.sendVerifyMessage(centerManagerVerifyEvent) + } + +} diff --git a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/service/CenterManagerVerifyEventService.kt b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/service/CenterManagerVerifyEventService.kt new file mode 100644 index 00000000..4b4f549f --- /dev/null +++ b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/service/CenterManagerVerifyEventService.kt @@ -0,0 +1,39 @@ +package com.swm.idle.infrastructure.client.discord.user.center.service + +import com.swm.idle.domain.user.center.event.CenterManagerVerifyEvent +import com.swm.idle.infrastructure.client.discord.common.event.EventType +import com.swm.idle.infrastructure.client.discord.common.properties.DiscordClientProperties +import com.swm.idle.infrastructure.client.discord.common.utils.DiscordMessageClient +import com.swm.idle.infrastructure.client.discord.common.vo.DiscordMessage +import io.github.oshai.kotlinlogging.KotlinLogging +import org.springframework.stereotype.Component +import java.net.URI + +@Component +class CenterManagerVerifyEventService( + private val discordMessageClient: DiscordMessageClient, + private val discordClientProperties: DiscordClientProperties, +) { + + private val logger = KotlinLogging.logger { } + + fun sendVerifyMessage(centerManagerVerifyEvent: CenterManagerVerifyEvent) { + + if (this.discordClientProperties.events.getValue(EventType.CENTER_MANAGER_VERIFICATION).active) { + val discordUri = + URI(this.discordClientProperties.events.getValue(EventType.CENTER_MANAGER_VERIFICATION).url) + val message = + "[🌟새로운 센터 관리자 ${centerManagerVerifyEvent.centerManager.name} 님이 관리자 인증 요청을 보냈어요! 빠르게 확인해주세요 :)" + + runCatching { + discordMessageClient.send( + uri = discordUri, + message = DiscordMessage(message), + ) + }.onFailure { + logger.error(it) { "💥센터 관리자 인증 요청 발생! 디스코드 메세지 전송에 실패했습니다." } + } + } + } + +} diff --git a/idle-infrastructure/client/src/main/resources/application-client.yml b/idle-infrastructure/client/src/main/resources/application-client.yml index 5a9449e4..6580bd27 100644 --- a/idle-infrastructure/client/src/main/resources/application-client.yml +++ b/idle-infrastructure/client/src/main/resources/application-client.yml @@ -8,3 +8,21 @@ geocode: client-id: ${NAVER_MAP_API_CLIENT_ID} client-secret: ${NAVER_MAP_API_CLIENT_SECRET} base-url: ${NAVER_MAP_API_REQUEST_URL} + +client: + events: + center-manager-verification: + active: true + url: https://discord.com/api/webhooks/1287686530143617034/eeh-aBBsR2kd8KV2COCF5BCv-y6Oo-fGFCyQBcsYBobVEsNcpHMcHfP3dYWgG8ERoHGC + +--- +spring: + config: + activate: + on-profile: prod + +client: + events: + center-manager-verification: + active: true + url: https://discord.com/api/webhooks/1287686530143617034/eeh-aBBsR2kd8KV2COCF5BCv-y6Oo-fGFCyQBcsYBobVEsNcpHMcHfP3dYWgG8ERoHGC From 945414a66968c7b7abf66a4d1868264f1966ea60 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 23 Sep 2024 17:38:43 +0900 Subject: [PATCH 039/108] =?UTF-8?q?[IDLE-389]=20=EC=82=AC=EC=97=85?= =?UTF-8?q?=EC=9E=90=20=EB=93=B1=EB=A1=9D=EB=B2=88=ED=98=B8=20client=20pro?= =?UTF-8?q?perties=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ties.kt => BusinessRegistrationNumberProperties.kt} | 2 +- .../BusinessRegistrationNumberValidationService.kt | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) rename idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/properties/{ClientProperties.kt => BusinessRegistrationNumberProperties.kt} (86%) diff --git a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/properties/ClientProperties.kt b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/properties/BusinessRegistrationNumberProperties.kt similarity index 86% rename from idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/properties/ClientProperties.kt rename to idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/properties/BusinessRegistrationNumberProperties.kt index 70937804..ac929d5d 100644 --- a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/properties/ClientProperties.kt +++ b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/properties/BusinessRegistrationNumberProperties.kt @@ -3,7 +3,7 @@ package com.swm.idle.infrastructure.client.businessregistration.properties import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties("business-registration-number") -class ClientProperties( +class BusinessRegistrationNumberProperties( val apikey: String, val path: String, val searchType: String, diff --git a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/service/BusinessRegistrationNumberValidationService.kt b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/service/BusinessRegistrationNumberValidationService.kt index f63987e5..c85e4428 100644 --- a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/service/BusinessRegistrationNumberValidationService.kt +++ b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/businessregistration/service/BusinessRegistrationNumberValidationService.kt @@ -3,14 +3,14 @@ package com.swm.idle.infrastructure.client.businessregistration.service import com.swm.idle.domain.user.center.vo.BusinessRegistrationNumber import com.swm.idle.infrastructure.client.businessregistration.dto.BusinessRegistrationNumberValidationResponse import com.swm.idle.infrastructure.client.businessregistration.exception.BusinessRegistrationException -import com.swm.idle.infrastructure.client.businessregistration.properties.ClientProperties +import com.swm.idle.infrastructure.client.businessregistration.properties.BusinessRegistrationNumberProperties import com.swm.idle.infrastructure.client.businessregistration.util.BusinessRegistrationNumberValidationClient import org.springframework.stereotype.Service import java.net.URI @Service class BusinessRegistrationNumberValidationService( - val clientProperties: ClientProperties, + val businessRegistrationNumberProperties: BusinessRegistrationNumberProperties, val businessRegistrationNumberValidationClient: BusinessRegistrationNumberValidationClient, ) { @@ -27,9 +27,9 @@ class BusinessRegistrationNumberValidationService( } private fun generateRequestUri(businessRegistrationNumber: BusinessRegistrationNumber): String { - return clientProperties.path + QUERY_PARAMETER_PREFIX + - "key=" + clientProperties.apikey + QUERY_PARAMETER_SUFFIX + - "gb=" + clientProperties.searchType + QUERY_PARAMETER_SUFFIX + + return businessRegistrationNumberProperties.path + QUERY_PARAMETER_PREFIX + + "key=" + businessRegistrationNumberProperties.apikey + QUERY_PARAMETER_SUFFIX + + "gb=" + businessRegistrationNumberProperties.searchType + QUERY_PARAMETER_SUFFIX + "q=" + businessRegistrationNumber.value + QUERY_PARAMETER_SUFFIX + "type=" + RESPONSE_TYPE } From f4a298d8971bbf9906049ebd67a177b2d854e40e Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 24 Sep 2024 18:16:13 +0900 Subject: [PATCH 040/108] =?UTF-8?q?[IDLE-389]=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/center/listener/CenterManagerEventListener.kt | 4 ++-- .../client/src/main/resources/application-client.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/listener/CenterManagerEventListener.kt b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/listener/CenterManagerEventListener.kt index ac6d8e14..8d92d2b8 100644 --- a/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/listener/CenterManagerEventListener.kt +++ b/idle-infrastructure/client/src/main/kotlin/com/swm/idle/infrastructure/client/discord/user/center/listener/CenterManagerEventListener.kt @@ -7,12 +7,12 @@ import org.springframework.stereotype.Component @Component class CenterManagerEventListener( - private val centerMangerVerifyEventService: CenterManagerVerifyEventService, + private val centerManagerVerifyEventService: CenterManagerVerifyEventService, ) { @EventListener fun handleCenterManagerVerifyEvent(centerManagerVerifyEvent: CenterManagerVerifyEvent) { - centerMangerVerifyEventService.sendVerifyMessage(centerManagerVerifyEvent) + centerManagerVerifyEventService.sendVerifyMessage(centerManagerVerifyEvent) } } diff --git a/idle-infrastructure/client/src/main/resources/application-client.yml b/idle-infrastructure/client/src/main/resources/application-client.yml index 6580bd27..ff0d76e2 100644 --- a/idle-infrastructure/client/src/main/resources/application-client.yml +++ b/idle-infrastructure/client/src/main/resources/application-client.yml @@ -12,7 +12,7 @@ geocode: client: events: center-manager-verification: - active: true + active: false url: https://discord.com/api/webhooks/1287686530143617034/eeh-aBBsR2kd8KV2COCF5BCv-y6Oo-fGFCyQBcsYBobVEsNcpHMcHfP3dYWgG8ERoHGC --- From 97a048587cc9d2d5ed959893795aebc2464a13e7 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 25 Sep 2024 17:50:01 +0900 Subject: [PATCH 041/108] =?UTF-8?q?[IDLE-000]=20=ED=8A=B8=EB=9E=9C?= =?UTF-8?q?=EC=9E=AD=EC=85=98=20=EC=A0=84=ED=8C=8C=20=EB=A0=88=EB=B2=A8=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD(REQUIRED=20->=20REQUIRES=5FNEW)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/center/service/facade/CenterAuthFacadeService.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt index 9705cc88..f4467be9 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/facade/CenterAuthFacadeService.kt @@ -23,6 +23,7 @@ import com.swm.idle.support.transfer.auth.center.ValidateBusinessRegistrationNum import com.swm.idle.support.transfer.auth.common.LoginResponse import com.swm.idle.support.transfer.user.center.JoinStatusInfoResponse import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Propagation import org.springframework.transaction.annotation.Transactional @Service @@ -139,7 +140,7 @@ class CenterAuthFacadeService( centerManagerService.updatePassword(centerManager, newPassword) } - @Transactional + @Transactional(propagation = Propagation.REQUIRES_NEW) fun requestCenterManagerVerification() { val centerManager = getUserAuthentication().userId .let { centerManagerService.getById(it) } From f897da2d50188e9ba4efa07485e33936535e483b Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Sat, 28 Sep 2024 21:08:49 +0900 Subject: [PATCH 042/108] =?UTF-8?q?[IDLE-396]=20FCM=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20firebase=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-deployer.yaml | 5 ++++ .github/workflows/prod-server-deployer.yaml | 5 ++++ .gitignore | 3 ++ build.gradle.kts | 1 - gradle/libs.versions.toml | 4 +++ idle-infrastructure/fcm/build.gradle.kts | 13 +++++++++ .../fcm/common/config/FcmConfig.kt | 29 +++++++++++++++++++ .../src/main/resources/application-fcm.yaml | 3 ++ settings.gradle.kts | 3 ++ 9 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 idle-infrastructure/fcm/build.gradle.kts create mode 100644 idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt create mode 100644 idle-infrastructure/fcm/src/main/resources/application-fcm.yaml diff --git a/.github/workflows/dev-server-deployer.yaml b/.github/workflows/dev-server-deployer.yaml index 099528a2..81568b50 100644 --- a/.github/workflows/dev-server-deployer.yaml +++ b/.github/workflows/dev-server-deployer.yaml @@ -43,6 +43,11 @@ jobs: --port 22 \ --cidr ${{ steps.publicip.outputs.ip }}/32 + - name: Set Up Firebase Service Key + run : | + mkdir ./idle-infrastructure/fcm/main/resources/firebase + echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > /idle-infrastructure/fcm/main/resources/firebase/adminkey.json + - name: Copy Docker Compose file to server uses: appleboy/scp-action@master with: diff --git a/.github/workflows/prod-server-deployer.yaml b/.github/workflows/prod-server-deployer.yaml index 1a75092f..60fa9612 100644 --- a/.github/workflows/prod-server-deployer.yaml +++ b/.github/workflows/prod-server-deployer.yaml @@ -73,6 +73,11 @@ jobs: jq -s '.[0] * .[1]' <(echo "$VARS_CONTEXT") <(echo "$SECRETS_CONTEXT") \ | jq -r 'to_entries | map("\(.key)=\(.value)") | .[]' > .env + - name: Set Up Firebase Service Key + run: | + mkdir ./idle-infrastructure/fcm/main/resources/firebase + echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > /idle-infrastructure/fcm/main/resources/firebase/adminkey.json + - name: Run Docker uses: appleboy/ssh-action@master with: diff --git a/.gitignore b/.gitignore index 5a979af6..8182d514 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,6 @@ out/ ### Kotlin ### .kotlin + +### JSON ### +idle-infrastructure/fcm/src/main/resources/firebase diff --git a/build.gradle.kts b/build.gradle.kts index 8d8c9e7f..20109a45 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,7 +43,6 @@ subprojects { implementation(rootProject.libs.locationtech) implementation(rootProject.libs.jakarta.persistence.api) implementation(rootProject.libs.jackson.module.kotlin) - implementation(rootProject.libs.sentry.spring.boot.starter.jakarta) implementation(rootProject.libs.sentry.logback) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dcfc37ea..98b66500 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -43,6 +43,8 @@ jackson-module-kotlin = "2.17.0" sentry = "7.14.0" +fcm = "9.3.0" + [libraries] kotlin-reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" } kotlin-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlin-coroutines" } @@ -101,6 +103,8 @@ jackson-module-kotlin = { group = "com.fasterxml.jackson.module", name = "jackso sentry-spring-boot-starter-jakarta = { group = "io.sentry", name = "sentry-spring-boot-starter-jakarta", version.ref = "sentry" } sentry-logback = { group = "io.sentry", name = "sentry-logback", version.ref = "sentry" } +fcm = { group = 'com.google.firebase', name = 'firebase-admin', version.ref = "fcm"} + [plugins] sonarqube = { id = "org.sonarqube", version.ref = "sonar-cloud" } spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" } diff --git a/idle-infrastructure/fcm/build.gradle.kts b/idle-infrastructure/fcm/build.gradle.kts new file mode 100644 index 00000000..494e44b8 --- /dev/null +++ b/idle-infrastructure/fcm/build.gradle.kts @@ -0,0 +1,13 @@ +import org.springframework.boot.gradle.tasks.bundling.BootJar + +val jar: Jar by tasks +val bootJar: BootJar by tasks + +bootJar.enabled = false +jar.enabled = true + +dependencies { + implementation(project(":idle-support:common")) + + implementation(rootProject.libs.fcm) +} diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt new file mode 100644 index 00000000..692678a7 --- /dev/null +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt @@ -0,0 +1,29 @@ +package com.swm.idle.infrastructure.fcm.common.config + +import com.google.auth.oauth2.GoogleCredentials +import com.google.firebase.FirebaseApp +import com.google.firebase.FirebaseOptions +import jakarta.annotation.PostConstruct +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Configuration +import org.springframework.core.io.ClassPathResource + +@Configuration +class FcmConfig { + + @Value("\${firebase.json.path}") + lateinit var firebaseConfigJsonPath: String + + @PostConstruct + fun initializeFirebaseApp() { + val googleCredentials = + GoogleCredentials.fromStream(ClassPathResource(firebaseConfigJsonPath).inputStream) + + val fireBaseOptions = FirebaseOptions.builder() + .setCredentials(googleCredentials) + .build() + + FirebaseApp.initializeApp(fireBaseOptions) + } + +} diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yaml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yaml new file mode 100644 index 00000000..68a7dd3c --- /dev/null +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yaml @@ -0,0 +1,3 @@ +firebase: + json: + path: ./firebase/adminsdk.json diff --git a/settings.gradle.kts b/settings.gradle.kts index f1c00e87..37a887ae 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -22,6 +22,9 @@ project(":idle-infrastructure:client").projectDir = file("idle-infrastructure/cl include(":idle-infrastructure:sms") project(":idle-infrastructure:sms").projectDir = file("idle-infrastructure/sms") +include(":idle-infrastructure:fcm") +project(":idle-infrastructure:fcm").projectDir = file("idle-infrastructure/fcm") + // support modules include(":idle-support:common") project(":idle-support:common").projectDir = file("idle-support/common") From 9b3e8bf45b8d16cced57374d0584ab2a888d7f67 Mon Sep 17 00:00:00 2001 From: Wonjun You <59856002+wonjunYou@users.noreply.github.com> Date: Sat, 28 Sep 2024 21:37:22 +0900 Subject: [PATCH 043/108] =?UTF-8?q?readme=20=EC=A0=9C=EB=AA=A9=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ea338b80..1dd3406c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 👋 반갑습니다! 세 얼간이 입니다! +# 쉽고 빠른 재가요양 시장의 구인구직 서비스, 케어밋(Caremeet) ppt_표지
From 6ab39e8f08c5f6b5ef6f33dc10c6d696bb6aecea Mon Sep 17 00:00:00 2001 From: Wonjun You <59856002+wonjunYou@users.noreply.github.com> Date: Sat, 28 Sep 2024 21:39:44 +0900 Subject: [PATCH 044/108] =?UTF-8?q?readme=20=EC=A0=9C=EB=AA=A9=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1dd3406c..ec8e0432 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 쉽고 빠른 재가요양 시장의 구인구직 서비스, 케어밋(Caremeet) +# 케어밋(Caremeet) : 쉽고 빠른 요양 보호사 구인 구직 서비스 ppt_표지
From 09df26bd44e2916c05c08b0ee125f83b90156194 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 1 Oct 2024 21:01:21 +0900 Subject: [PATCH 045/108] =?UTF-8?q?[IDLE-399]=20FCM=20Device=20Token=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/domain/DeviceTokenService.kt | 48 +++++++++++++++++++ .../facade/DeviceTokenFacadeService.kt | 30 ++++++++++++ .../domain/notification/jpa/DeviceToken.kt | 36 ++++++++++++++ .../repository/DeviceTokenJpaRepository.kt | 15 ++++++ .../notification/api/DeviceTokenApi.kt | 31 ++++++++++++ .../controller/DeviceTokenController.kt | 25 ++++++++++ .../notification/CreateDeviceTokenRequest.kt | 16 +++++++ .../notification/DeleteDeviceTokenRequest.kt | 12 +++++ 8 files changed, 213 insertions(+) create mode 100644 idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt create mode 100644 idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/DeviceTokenFacadeService.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/DeviceToken.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt create mode 100644 idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/DeviceTokenApi.kt create mode 100644 idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/DeviceTokenController.kt create mode 100644 idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/CreateDeviceTokenRequest.kt create mode 100644 idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/DeleteDeviceTokenRequest.kt diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt new file mode 100644 index 00000000..dee9f100 --- /dev/null +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt @@ -0,0 +1,48 @@ +package com.swm.idle.application.notification.domain + +import com.swm.idle.domain.notification.jpa.DeviceToken +import com.swm.idle.domain.notification.repository.DeviceTokenJpaRepository +import com.swm.idle.domain.user.common.enum.UserType +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.util.* + +@Service +@Transactional(readOnly = true) +class DeviceTokenService( + private val deviceTokenJpaRepository: DeviceTokenJpaRepository, +) { + + fun findByDeviceToken(deviceToken: String): DeviceToken? { + return deviceTokenJpaRepository.findByDeviceToken(deviceToken) + } + + @Transactional + fun updateDeviceTokenUserId( + deviceToken: DeviceToken, + userId: UUID, + ) { + deviceToken.updateUserId(userId) + } + + @Transactional + fun deleteByDeviceToken(deviceToken: String) { + deviceTokenJpaRepository.deleteByDeviceToken(deviceToken) + } + + @Transactional + fun save( + userId: UUID, + deviceToken: String, + userType: UserType, + ) { + DeviceToken( + userId = userId, + deviceToken = deviceToken, + userType = userType, + ).also { + deviceTokenJpaRepository.save(it) + } + } + +} diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/DeviceTokenFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/DeviceTokenFacadeService.kt new file mode 100644 index 00000000..3ffa1187 --- /dev/null +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/DeviceTokenFacadeService.kt @@ -0,0 +1,30 @@ +package com.swm.idle.application.notification.facade + +import com.swm.idle.application.common.security.getUserAuthentication +import com.swm.idle.application.notification.domain.DeviceTokenService +import com.swm.idle.domain.user.common.enum.UserType +import org.springframework.stereotype.Service + +@Service +class DeviceTokenFacadeService( + private val deviceTokenService: DeviceTokenService, +) { + + fun createDeviceToken(deviceToken: String, userType: UserType) { + val userId = getUserAuthentication().userId + deviceTokenService.findByDeviceToken(deviceToken)?.let { + if (it.userId != userId) { + deviceTokenService.updateDeviceTokenUserId(it, userId) + } + } ?: deviceTokenService.save( + userId = userId, + deviceToken = deviceToken, + userType = userType, + ) + } + + fun deleteDeviceToken(deviceToken: String) { + deviceTokenService.deleteByDeviceToken(deviceToken) + } + +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/DeviceToken.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/DeviceToken.kt new file mode 100644 index 00000000..e8e42469 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/DeviceToken.kt @@ -0,0 +1,36 @@ +package com.swm.idle.domain.notification.jpa + +import com.swm.idle.domain.common.entity.BaseEntity +import com.swm.idle.domain.user.common.enum.UserType +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.EnumType +import jakarta.persistence.Enumerated +import jakarta.persistence.Table +import java.util.* + +@Entity +@Table(name = "device_token") +class DeviceToken( + deviceToken: String, + userId: UUID, + userType: UserType, +) : BaseEntity() { + + @Column(columnDefinition = "varchar(255)") + var deviceToken: String = deviceToken + private set + + var userId: UUID = userId + private set + + @Enumerated(EnumType.STRING) + @Column(columnDefinition = "varchar(255)") + var userType: UserType = userType + private set + + fun updateUserId(userId: UUID) { + this.userId = userId + } + +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt new file mode 100644 index 00000000..575aa21b --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt @@ -0,0 +1,15 @@ +package com.swm.idle.domain.notification.repository + +import com.swm.idle.domain.notification.jpa.DeviceToken +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository +import java.util.* + +@Repository +interface DeviceTokenJpaRepository : JpaRepository { + + fun findByDeviceToken(deviceToken: String): DeviceToken? + + fun deleteByDeviceToken(deviceToken: String) + +} diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/DeviceTokenApi.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/DeviceTokenApi.kt new file mode 100644 index 00000000..3362f8cf --- /dev/null +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/DeviceTokenApi.kt @@ -0,0 +1,31 @@ +package com.swm.idle.presentation.notification.api + +import com.swm.idle.presentation.common.security.annotation.Secured +import com.swm.idle.support.transfer.notification.CreateDeviceTokenRequest +import com.swm.idle.support.transfer.notification.DeleteDeviceTokenRequest +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.http.HttpStatus +import org.springframework.web.bind.annotation.DeleteMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.ResponseStatus + +@Tag(name = "FCM Device Token", description = "FCM 디바이스 토큰 API") +@RequestMapping("/api/v1/fcm", produces = ["application/json;charset=utf-8"]) +interface DeviceTokenApi { + + @Secured + @Operation(summary = "FCM 토큰 저장 API") + @PostMapping("/token") + @ResponseStatus(HttpStatus.CREATED) + fun createDeviceToken(@RequestBody request: CreateDeviceTokenRequest) + + @Secured + @Operation(summary = "FCM 토큰 삭제 API") + @DeleteMapping("/token") + @ResponseStatus(HttpStatus.NO_CONTENT) + fun deleteDeviceToken(@RequestBody request: DeleteDeviceTokenRequest) + +} diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/DeviceTokenController.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/DeviceTokenController.kt new file mode 100644 index 00000000..2271b725 --- /dev/null +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/DeviceTokenController.kt @@ -0,0 +1,25 @@ +package com.swm.idle.presentation.notification.controller + +import com.swm.idle.application.notification.facade.DeviceTokenFacadeService +import com.swm.idle.presentation.notification.api.DeviceTokenApi +import com.swm.idle.support.transfer.notification.CreateDeviceTokenRequest +import com.swm.idle.support.transfer.notification.DeleteDeviceTokenRequest +import org.springframework.web.bind.annotation.RestController + +@RestController +class DeviceTokenController( + private val deviceTokenFacadeService: DeviceTokenFacadeService, +) : DeviceTokenApi { + + override fun createDeviceToken(request: CreateDeviceTokenRequest) { + deviceTokenFacadeService.createDeviceToken( + deviceToken = request.deviceToken, + userType = request.userType, + ) + } + + override fun deleteDeviceToken(request: DeleteDeviceTokenRequest) { + deviceTokenFacadeService.deleteDeviceToken(request.deviceToken) + } + +} diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/CreateDeviceTokenRequest.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/CreateDeviceTokenRequest.kt new file mode 100644 index 00000000..e3026b7a --- /dev/null +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/CreateDeviceTokenRequest.kt @@ -0,0 +1,16 @@ +package com.swm.idle.support.transfer.notification + +import com.swm.idle.domain.user.common.enum.UserType +import io.swagger.v3.oas.annotations.media.Schema + +@Schema( + name = "CreateDeviceTokenRequest", + description = "FCM 토큰 저장 요청", +) +data class CreateDeviceTokenRequest( + @Schema(description = "fcm device token") + val deviceToken: String, + + @Schema(description = "user type") + val userType: UserType, +) diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/DeleteDeviceTokenRequest.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/DeleteDeviceTokenRequest.kt new file mode 100644 index 00000000..b59e18f7 --- /dev/null +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/DeleteDeviceTokenRequest.kt @@ -0,0 +1,12 @@ +package com.swm.idle.support.transfer.notification + +import io.swagger.v3.oas.annotations.media.Schema + +@Schema( + name = "DeleteDeviceTokenRequest", + description = "FCM 토큰 삭제 요청", +) +data class DeleteDeviceTokenRequest( + @Schema(description = "fcm device token") + val deviceToken: String, +) From a5da3314fe72c1ebfdfe5dda50e8623a9edacfc0 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 1 Oct 2024 21:01:43 +0900 Subject: [PATCH 046/108] =?UTF-8?q?[IDLE-399]=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/notification/jpa/Notification.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/Notification.kt diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/Notification.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/Notification.kt new file mode 100644 index 00000000..a7793b2d --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/Notification.kt @@ -0,0 +1,33 @@ +package com.swm.idle.domain.notification.jpa + +import com.swm.idle.domain.common.entity.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Table +import java.util.* + +@Entity +@Table(name = "notification") +class Notification( + isRead: Boolean, + title: String, + body: String, + receiverId: UUID, +) : BaseEntity() { + + @Column(columnDefinition = "varchar(255)") + var isRead: Boolean = isRead + private set + + @Column(columnDefinition = "varchar(255)") + var title: String = title + private set + + @Column(columnDefinition = "varchar(255)") + var body: String = body + private set + + var receiverId: UUID = receiverId + private set + +} From 9e63a8129edbed31d5253940b03ffd241929d3c2 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 2 Oct 2024 11:27:18 +0900 Subject: [PATCH 047/108] =?UTF-8?q?[IDLE-000]=20fcm=20service=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EA=B0=92=20=EC=A3=BC=EC=9E=85=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EB=94=94=EB=A0=89=ED=86=A0=EB=A6=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-deployer.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-deployer.yaml b/.github/workflows/dev-server-deployer.yaml index 81568b50..b712000c 100644 --- a/.github/workflows/dev-server-deployer.yaml +++ b/.github/workflows/dev-server-deployer.yaml @@ -45,7 +45,7 @@ jobs: - name: Set Up Firebase Service Key run : | - mkdir ./idle-infrastructure/fcm/main/resources/firebase + mkdir ./src/main/resources/firebase echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > /idle-infrastructure/fcm/main/resources/firebase/adminkey.json - name: Copy Docker Compose file to server From d7fb9c48bfa8e6a49ff65dac5e2dd025573d62b5 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 2 Oct 2024 11:35:25 +0900 Subject: [PATCH 048/108] =?UTF-8?q?[IDLE-000]=20fcm=20service=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EA=B0=92=20=EC=A3=BC=EC=9E=85=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EB=94=94=EB=A0=89=ED=86=A0=EB=A6=AC=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-deployer.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-deployer.yaml b/.github/workflows/dev-server-deployer.yaml index b712000c..a042e3bf 100644 --- a/.github/workflows/dev-server-deployer.yaml +++ b/.github/workflows/dev-server-deployer.yaml @@ -46,7 +46,7 @@ jobs: - name: Set Up Firebase Service Key run : | mkdir ./src/main/resources/firebase - echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > /idle-infrastructure/fcm/main/resources/firebase/adminkey.json + echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > ./src/main/resources/firebase/adminkey.json - name: Copy Docker Compose file to server uses: appleboy/scp-action@master From e4055428da4908023a9e77f3134d607b17ae27cf Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Thu, 3 Oct 2024 18:45:48 +0900 Subject: [PATCH 049/108] =?UTF-8?q?[IDLE-400]=20=EC=B1=84=EC=9A=A9=20?= =?UTF-8?q?=EA=B3=B5=EA=B3=A0=20=EC=A7=80=EC=9B=90=EC=9E=90=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=20=EC=8B=9C,=20=EC=84=BC=ED=84=B0=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=EC=9E=90=EC=97=90=EA=B2=8C=20=EC=95=8C=EB=A6=BC?= =?UTF-8?q?=EC=9D=84=20=EB=B0=9C=EC=86=A1=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../applys/domain/CarerApplyEventPublisher.kt | 16 ++++++ .../applys/domain/CarerApplyService.kt | 4 +- .../applys/facade/CarerApplyFacadeService.kt | 42 ++++++++++++--- .../notification/domain/DeviceTokenService.kt | 4 ++ .../idle/domain/applys/event/ApplyEvent.kt | 25 +++++++++ .../repository/DeviceTokenJpaRepository.kt | 2 + .../domain/user/common/enum/GenderType.kt | 11 ++-- idle-infrastructure/fcm/build.gradle.kts | 1 + .../listener/CarerApplyEventListener.kt | 20 ++++++++ .../applys/service/CarerApplyEventService.kt | 51 +++++++++++++++++++ .../fcm/common/client/FcmClient.kt | 19 +++++++ .../fcm/common/config/FcmConfig.kt | 26 ++-------- .../fcm/common/config/FirebaseConfig.kt | 29 +++++++++++ .../fcm/common/enums/DestinationType.kt | 5 ++ 14 files changed, 218 insertions(+), 37 deletions(-) create mode 100644 idle-application/src/main/kotlin/com/swm/idle/application/applys/domain/CarerApplyEventPublisher.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt create mode 100644 idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt create mode 100644 idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt create mode 100644 idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt create mode 100644 idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt create mode 100644 idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/enums/DestinationType.kt diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/applys/domain/CarerApplyEventPublisher.kt b/idle-application/src/main/kotlin/com/swm/idle/application/applys/domain/CarerApplyEventPublisher.kt new file mode 100644 index 00000000..323acca2 --- /dev/null +++ b/idle-application/src/main/kotlin/com/swm/idle/application/applys/domain/CarerApplyEventPublisher.kt @@ -0,0 +1,16 @@ +package com.swm.idle.application.applys.domain + +import com.swm.idle.domain.applys.event.ApplyEvent +import org.springframework.context.ApplicationEventPublisher +import org.springframework.stereotype.Service + +@Service +class CarerApplyEventPublisher( + private val eventPublisher: ApplicationEventPublisher, +) { + + fun publish(applyEvent: ApplyEvent) { + eventPublisher.publishEvent(applyEvent) + } + +} diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/applys/domain/CarerApplyService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/applys/domain/CarerApplyService.kt index 82db35fd..86678677 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/applys/domain/CarerApplyService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/applys/domain/CarerApplyService.kt @@ -15,8 +15,8 @@ class CarerApplyService( jobPostingId: UUID, carerId: UUID, applyMethodType: ApplyMethodType, - ) { - carerApplyJpaRepository.save( + ): Applys { + return carerApplyJpaRepository.save( Applys( jobPostingId = jobPostingId, carerId = carerId, diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt index a132db3a..a530a9bc 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt @@ -1,10 +1,17 @@ package com.swm.idle.application.applys.facade +import com.swm.idle.application.applys.domain.CarerApplyEventPublisher import com.swm.idle.application.applys.domain.CarerApplyService import com.swm.idle.application.common.security.getUserAuthentication +import com.swm.idle.application.jobposting.domain.JobPostingService +import com.swm.idle.application.notification.domain.DeviceTokenService +import com.swm.idle.application.user.carer.domain.CarerService +import com.swm.idle.domain.applys.event.ApplyEvent import com.swm.idle.domain.applys.exception.ApplyException import com.swm.idle.domain.jobposting.enums.ApplyMethodType +import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Propagation import org.springframework.transaction.annotation.Transactional import java.util.* @@ -12,28 +19,47 @@ import java.util.* @Transactional(readOnly = true) class CarerApplyFacadeService( private val carerApplyService: CarerApplyService, + private val carerApplyEventPublisher: CarerApplyEventPublisher, + private val deviceTokenService: DeviceTokenService, + private val jobPostingService: JobPostingService, + private val carerService: CarerService, ) { - @Transactional + private val logger = KotlinLogging.logger { } + + @Transactional(propagation = Propagation.REQUIRES_NEW) fun createApply( jobPostingId: UUID, applyMethodType: ApplyMethodType, ) { - val carerId = getUserAuthentication().userId + val carer = getUserAuthentication().userId.let { + carerService.getById(it) + } + val deviceToken = deviceTokenService.findByUserId(carer.id) + val jobPosting = jobPostingService.getById(jobPostingId) if (carerApplyService.existsByJobPostingIdAndCarerId( jobPostingId = jobPostingId, - carerId = carerId, + carerId = carer.id, ) ) { throw ApplyException.AlreadyApplied() } - carerApplyService.create( - jobPostingId = jobPostingId, - carerId = carerId, - applyMethodType = applyMethodType, - ) + carerApplyService.create(jobPostingId, carer.id, applyMethodType) + + deviceToken?.let { + carerApplyEventPublisher.publish( + ApplyEvent.createApplyEvent( + deviceToken = deviceToken, + jobPosting = jobPosting, + carer = carer, + ) + ) + } ?: run { + logger.warn { "${carer.id} 요양 보호사의 device Token이 존재하지 않아 알림이 발송되지 않았습니다." } + } + } } diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt index dee9f100..3d0a35bd 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt @@ -17,6 +17,10 @@ class DeviceTokenService( return deviceTokenJpaRepository.findByDeviceToken(deviceToken) } + fun findByUserId(userId: UUID): DeviceToken? { + return deviceTokenJpaRepository.findByUserId(userId) + } + @Transactional fun updateDeviceTokenUserId( deviceToken: DeviceToken, diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt new file mode 100644 index 00000000..4efe0734 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt @@ -0,0 +1,25 @@ +package com.swm.idle.domain.applys.event + +import com.swm.idle.domain.jobposting.entity.jpa.JobPosting +import com.swm.idle.domain.notification.jpa.DeviceToken +import com.swm.idle.domain.user.carer.entity.jpa.Carer + +data class ApplyEvent( + val deviceToken: DeviceToken, + val jobPosting: JobPosting, + val carer: Carer, +) { + + companion object { + + fun createApplyEvent( + deviceToken: DeviceToken, + jobPosting: JobPosting, + carer: Carer, + ): ApplyEvent { + return ApplyEvent(deviceToken, jobPosting, carer) + } + + } + +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt index 575aa21b..62aaf96c 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt @@ -12,4 +12,6 @@ interface DeviceTokenJpaRepository : JpaRepository { fun deleteByDeviceToken(deviceToken: String) + fun findByUserId(userId: UUID): DeviceToken? + } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/enum/GenderType.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/enum/GenderType.kt index f8e74d88..fd7882a7 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/enum/GenderType.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/common/enum/GenderType.kt @@ -1,6 +1,9 @@ package com.swm.idle.domain.user.common.enum -enum class GenderType { - MAN, - WOMAN; -} \ No newline at end of file +enum class GenderType( + val value: String, +) { + + MAN("남성"), + WOMAN("여성"); +} diff --git a/idle-infrastructure/fcm/build.gradle.kts b/idle-infrastructure/fcm/build.gradle.kts index 494e44b8..dbca75c8 100644 --- a/idle-infrastructure/fcm/build.gradle.kts +++ b/idle-infrastructure/fcm/build.gradle.kts @@ -7,6 +7,7 @@ bootJar.enabled = false jar.enabled = true dependencies { + implementation(project(":idle-domain")) implementation(project(":idle-support:common")) implementation(rootProject.libs.fcm) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt new file mode 100644 index 00000000..cca7d92f --- /dev/null +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt @@ -0,0 +1,20 @@ +package com.swm.idle.infrastructure.fcm.applys.listener + +import com.swm.idle.domain.applys.event.ApplyEvent +import com.swm.idle.infrastructure.fcm.applys.service.CarerApplyEventService +import org.springframework.context.event.EventListener +import org.springframework.stereotype.Component + +@Component + +class CarerApplyEventListener( + private val carerApplyEventService: CarerApplyEventService, +) { + + @EventListener + fun handleCarerApplyEvent(applyEvent: ApplyEvent) { + carerApplyEventService.send(applyEvent) + } + +} + diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt new file mode 100644 index 00000000..61687945 --- /dev/null +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt @@ -0,0 +1,51 @@ +package com.swm.idle.infrastructure.fcm.applys.service + +import com.google.firebase.messaging.Message +import com.google.firebase.messaging.Notification +import com.swm.idle.domain.applys.event.ApplyEvent +import com.swm.idle.domain.user.common.vo.BirthYear +import com.swm.idle.infrastructure.fcm.common.client.FcmClient +import com.swm.idle.infrastructure.fcm.common.enums.DestinationType +import org.springframework.stereotype.Component + +@Component +class CarerApplyEventService( + private val fcmClient: FcmClient, +) { + + fun send(applyEvent: ApplyEvent) { + createMessage(applyEvent).also { + fcmClient.send(it) + } + } + + private fun createApplyNotification(applyEvent: ApplyEvent): Notification { + return Notification.builder() + .setTitle("${applyEvent.carer.name} 님이 공고에 지원하였습니다.") + .setBody(createBodyMessage(applyEvent)) + .build() + } + + private fun createBodyMessage(applyEvent: ApplyEvent): String? { + val filteredLotNumberAddress = applyEvent.jobPosting.lotNumberAddress.split(" ") + .take(3) + .joinToString(" ") + + return "$filteredLotNumberAddress " + + "${applyEvent.jobPosting.careLevel}등급 " + + "${BirthYear.calculateAge(applyEvent.jobPosting.birthYear)}세 " + + applyEvent.jobPosting.gender.value + } + + private fun createMessage(applyEvent: ApplyEvent): Message { + val applyNotification = createApplyNotification(applyEvent) + + return Message.builder() + .setToken(applyEvent.deviceToken.deviceToken) + .setNotification(applyNotification) + .putData("destination", DestinationType.APPLICANTS.toString()) + .putData("jobPostingId", applyEvent.jobPosting.id.toString()) + .build(); + } + +} diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt new file mode 100644 index 00000000..33e5aa67 --- /dev/null +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt @@ -0,0 +1,19 @@ +package com.swm.idle.infrastructure.fcm.common.client + +import com.google.firebase.messaging.FirebaseMessaging +import com.google.firebase.messaging.Message +import org.springframework.stereotype.Component + +@Component +class FcmClient { + + fun send(message: Message) { + firebase.sendAsync(message) + } + + companion object { + + val firebase: FirebaseMessaging = FirebaseMessaging.getInstance() + } + +} diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt index 692678a7..1755a994 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt @@ -1,29 +1,9 @@ package com.swm.idle.infrastructure.fcm.common.config -import com.google.auth.oauth2.GoogleCredentials -import com.google.firebase.FirebaseApp -import com.google.firebase.FirebaseOptions -import jakarta.annotation.PostConstruct -import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration -import org.springframework.core.io.ClassPathResource @Configuration -class FcmConfig { - - @Value("\${firebase.json.path}") - lateinit var firebaseConfigJsonPath: String - - @PostConstruct - fun initializeFirebaseApp() { - val googleCredentials = - GoogleCredentials.fromStream(ClassPathResource(firebaseConfigJsonPath).inputStream) - - val fireBaseOptions = FirebaseOptions.builder() - .setCredentials(googleCredentials) - .build() - - FirebaseApp.initializeApp(fireBaseOptions) - } - +@ComponentScan(basePackages = ["com.swm.idle.infrastructure.fcm"]) +interface FcmConfig { } diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt new file mode 100644 index 00000000..7ecd9d1e --- /dev/null +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -0,0 +1,29 @@ +package com.swm.idle.infrastructure.fcm.common.config + +import com.google.auth.oauth2.GoogleCredentials +import com.google.firebase.FirebaseApp +import com.google.firebase.FirebaseOptions +import jakarta.annotation.PostConstruct +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Configuration +import org.springframework.core.io.ClassPathResource + +@Configuration +class FirebaseConfig { + + @Value("\${firebase.json.path}") + lateinit var firebaseConfigJsonPath: String + + @PostConstruct + fun initializeFirebaseApp() { + val googleCredentials = + GoogleCredentials.fromStream(ClassPathResource(firebaseConfigJsonPath).inputStream) + + val fireBaseOptions = FirebaseOptions.builder() + .setCredentials(googleCredentials) + .build() + + FirebaseApp.initializeApp(fireBaseOptions) + } + +} diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/enums/DestinationType.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/enums/DestinationType.kt new file mode 100644 index 00000000..ac761461 --- /dev/null +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/enums/DestinationType.kt @@ -0,0 +1,5 @@ +package com.swm.idle.infrastructure.fcm.common.enums + +enum class DestinationType { + APPLICANTS +} From 0f84a0062d8dce90fed1ba0cc7ca4fe80fa6738d Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 14 Oct 2024 18:07:09 +0900 Subject: [PATCH 050/108] =?UTF-8?q?[IDLE-400]=20fcm=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idle-application/build.gradle.kts | 1 + .../swm/idle/infrastructure/fcm/common/config/FcmConfig.kt | 6 +++++- .../idle/infrastructure/fcm/common/config/FirebaseConfig.kt | 6 +++--- .../fcm/src/main/resources/application-fcm.yaml | 3 --- .../fcm/src/main/resources/application-fcm.yml | 3 +++ idle-presentation/build.gradle.kts | 1 + .../com/swm/idle/presentation/IdleServerApplication.kt | 2 ++ idle-presentation/src/main/resources/application.yml | 1 + 8 files changed, 16 insertions(+), 7 deletions(-) delete mode 100644 idle-infrastructure/fcm/src/main/resources/application-fcm.yaml create mode 100644 idle-infrastructure/fcm/src/main/resources/application-fcm.yml diff --git a/idle-application/build.gradle.kts b/idle-application/build.gradle.kts index 7fcb11e9..1165de8b 100644 --- a/idle-application/build.gradle.kts +++ b/idle-application/build.gradle.kts @@ -10,6 +10,7 @@ dependencies { implementation(project(":idle-infrastructure:aws")) implementation(project(":idle-infrastructure:client")) implementation(project(":idle-infrastructure:sms")) + implementation(project(":idle-infrastructure:fcm")) implementation(project(":idle-support:common")) implementation(project(":idle-support:security")) implementation(project(":idle-support:transfer")) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt index 1755a994..2cfd9c02 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FcmConfig.kt @@ -1,9 +1,13 @@ package com.swm.idle.infrastructure.fcm.common.config +import org.springframework.boot.context.properties.ConfigurationPropertiesScan +import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration @Configuration @ComponentScan(basePackages = ["com.swm.idle.infrastructure.fcm"]) -interface FcmConfig { +@EnableConfigurationProperties +@ConfigurationPropertiesScan(basePackages = ["com.swm.idle.infrastructure.fcm"]) +class FcmConfig { } diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index 7ecd9d1e..739000f6 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -9,10 +9,10 @@ import org.springframework.context.annotation.Configuration import org.springframework.core.io.ClassPathResource @Configuration -class FirebaseConfig { - +class FirebaseConfig( @Value("\${firebase.json.path}") - lateinit var firebaseConfigJsonPath: String + var firebaseConfigJsonPath: String, +) { @PostConstruct fun initializeFirebaseApp() { diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yaml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yaml deleted file mode 100644 index 68a7dd3c..00000000 --- a/idle-infrastructure/fcm/src/main/resources/application-fcm.yaml +++ /dev/null @@ -1,3 +0,0 @@ -firebase: - json: - path: ./firebase/adminsdk.json diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml new file mode 100644 index 00000000..062a031e --- /dev/null +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml @@ -0,0 +1,3 @@ +firebase: + json: + path: ./firebase/swm-3idiots-firebase-adminsdk-si1at-8130a3deda.json diff --git a/idle-presentation/build.gradle.kts b/idle-presentation/build.gradle.kts index d220156a..db5162a8 100644 --- a/idle-presentation/build.gradle.kts +++ b/idle-presentation/build.gradle.kts @@ -9,6 +9,7 @@ dependencies { implementation(project(":idle-infrastructure:aws")) implementation(project(":idle-infrastructure:client")) implementation(project(":idle-infrastructure:sms")) + implementation(project(":idle-infrastructure:fcm")) implementation(libs.spring.boot.starter.web) implementation(libs.spring.boot.starter.data.jpa) diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt index 016909b2..16ccc1ba 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/IdleServerApplication.kt @@ -6,6 +6,7 @@ import com.swm.idle.domain.common.config.DomainConfig import com.swm.idle.domain.common.config.RedisConfig import com.swm.idle.infrastructure.aws.common.AwsConfig import com.swm.idle.infrastructure.client.common.config.ClientConfig +import com.swm.idle.infrastructure.fcm.common.config.FcmConfig import com.swm.idle.infrastructure.sms.common.config.SmsConfig import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -24,6 +25,7 @@ import java.util.* SmsConfig::class, AwsConfig::class, BatchConfig::class, + FcmConfig::class, ] ) class IdleServerApplication { diff --git a/idle-presentation/src/main/resources/application.yml b/idle-presentation/src/main/resources/application.yml index ffdb983e..2a9835cc 100644 --- a/idle-presentation/src/main/resources/application.yml +++ b/idle-presentation/src/main/resources/application.yml @@ -12,6 +12,7 @@ spring: - sms - client - batch + - fcm swagger: server: From 8257e43fb610862e080ce5c54d1c921b86c05a0d Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 14 Oct 2024 18:08:38 +0900 Subject: [PATCH 051/108] =?UTF-8?q?[IDLE-400]=20=EA=B3=B5=EA=B3=A0=20?= =?UTF-8?q?=EC=A7=80=EC=9B=90=EC=9E=90=20=EB=B0=9C=EC=83=9D=20=EC=8B=9C,?= =?UTF-8?q?=20=EB=AA=A8=EB=93=A0=20=EC=84=BC=ED=84=B0=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=EC=9E=90=EB=93=A4=EC=97=90=EA=B2=8C=20=EB=8B=A4=EC=A4=91=20?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=EC=9D=84=20=EB=B0=9C=EC=86=A1=ED=95=9C?= =?UTF-8?q?=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../applys/facade/CarerApplyFacadeService.kt | 44 ++++++++++++------- .../service/domain/CenterManagerService.kt | 6 +++ .../common/scheduler/CrawlingJobScheduler.kt | 1 - .../idle/domain/applys/event/ApplyEvent.kt | 6 +-- .../jpa/CenterManagerJpaRepository.kt | 8 ++-- .../listener/CarerApplyEventListener.kt | 5 +-- .../applys/service/CarerApplyEventService.kt | 21 +++++---- .../fcm/common/client/FcmClient.kt | 11 ++--- 8 files changed, 59 insertions(+), 43 deletions(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt index a530a9bc..f1904e9b 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt @@ -6,9 +6,14 @@ import com.swm.idle.application.common.security.getUserAuthentication import com.swm.idle.application.jobposting.domain.JobPostingService import com.swm.idle.application.notification.domain.DeviceTokenService import com.swm.idle.application.user.carer.domain.CarerService +import com.swm.idle.application.user.center.service.domain.CenterManagerService +import com.swm.idle.application.user.center.service.domain.CenterService import com.swm.idle.domain.applys.event.ApplyEvent import com.swm.idle.domain.applys.exception.ApplyException +import com.swm.idle.domain.common.enums.EntityStatus import com.swm.idle.domain.jobposting.enums.ApplyMethodType +import com.swm.idle.domain.user.center.enums.CenterManagerAccountStatus +import com.swm.idle.domain.user.center.vo.BusinessRegistrationNumber import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Propagation @@ -23,6 +28,8 @@ class CarerApplyFacadeService( private val deviceTokenService: DeviceTokenService, private val jobPostingService: JobPostingService, private val carerService: CarerService, + private val centerManagerService: CenterManagerService, + private val centerService: CenterService, ) { private val logger = KotlinLogging.logger { } @@ -35,31 +42,34 @@ class CarerApplyFacadeService( val carer = getUserAuthentication().userId.let { carerService.getById(it) } - val deviceToken = deviceTokenService.findByUserId(carer.id) val jobPosting = jobPostingService.getById(jobPostingId) - if (carerApplyService.existsByJobPostingIdAndCarerId( - jobPostingId = jobPostingId, - carerId = carer.id, - ) - ) { + if (carerApplyService.existsByJobPostingIdAndCarerId(jobPostingId, carer.id)) { throw ApplyException.AlreadyApplied() } - carerApplyService.create(jobPostingId, carer.id, applyMethodType) + val center = centerService.getById(jobPosting.centerId) + + val deviceTokens = centerManagerService.findAllByCenterBusinessRegistrationNumber( + BusinessRegistrationNumber(center.businessRegistrationNumber) + )?.filter { centerManager -> + centerManager.status == CenterManagerAccountStatus.APPROVED && centerManager.entityStatus == EntityStatus.ACTIVE + }?.mapNotNull { centerManager -> + deviceTokenService.findByUserId(centerManager.id) + } - deviceToken?.let { - carerApplyEventPublisher.publish( - ApplyEvent.createApplyEvent( - deviceToken = deviceToken, - jobPosting = jobPosting, - carer = carer, - ) - ) + deviceTokens?.let { + ApplyEvent.createApplyEvent( + deviceTokens = deviceTokens, + jobPosting = jobPosting, + carer = carer, + ).also { + carerApplyEventPublisher.publish(it) + } } ?: run { - logger.warn { "${carer.id} 요양 보호사의 device Token이 존재하지 않아 알림이 발송되지 않았습니다." } + logger.warn { "device Token이 존재하지 않아 알림이 발송되지 않았습니다." } } + carerApplyService.create(jobPostingId, carer.id, applyMethodType) } - } diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerService.kt index c0e5c42e..6fd56c9f 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/user/center/service/domain/CenterManagerService.kt @@ -85,4 +85,10 @@ class CenterManagerService( centerManager.updateAccountStatusToPending() } + fun findAllByCenterBusinessRegistrationNumber(centerBusinessRegistrationNumber: BusinessRegistrationNumber): List? { + return centerManagerJpaRepository.findAllByCenterBusinessRegistrationNumber( + centerBusinessRegistrationNumber.value + ) + } + } diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index 45d532fe..ba7ba550 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -23,4 +23,3 @@ class CrawlingJobScheduler( } } - diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt index 4efe0734..33800ef7 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt @@ -5,7 +5,7 @@ import com.swm.idle.domain.notification.jpa.DeviceToken import com.swm.idle.domain.user.carer.entity.jpa.Carer data class ApplyEvent( - val deviceToken: DeviceToken, + val deviceTokens: List, val jobPosting: JobPosting, val carer: Carer, ) { @@ -13,11 +13,11 @@ data class ApplyEvent( companion object { fun createApplyEvent( - deviceToken: DeviceToken, + deviceTokens: List, jobPosting: JobPosting, carer: Carer, ): ApplyEvent { - return ApplyEvent(deviceToken, jobPosting, carer) + return ApplyEvent(deviceTokens, jobPosting, carer) } } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/repository/jpa/CenterManagerJpaRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/repository/jpa/CenterManagerJpaRepository.kt index ae5ecce7..76fc4261 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/repository/jpa/CenterManagerJpaRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/user/center/repository/jpa/CenterManagerJpaRepository.kt @@ -8,10 +8,12 @@ import java.util.* @Repository interface CenterManagerJpaRepository : JpaRepository { - fun findByIdentifier(value: String): CenterManager? + fun findByIdentifier(identifier: String): CenterManager? - fun existsByIdentifier(value: String): Boolean + fun existsByIdentifier(identifier: String): Boolean - fun findByPhoneNumber(value: String): CenterManager? + fun findByPhoneNumber(phoneNumber: String): CenterManager? + + fun findAllByCenterBusinessRegistrationNumber(centerBusinessRegistrationNumber: String): List? } diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt index cca7d92f..4ee5a9ec 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt @@ -6,14 +6,13 @@ import org.springframework.context.event.EventListener import org.springframework.stereotype.Component @Component - class CarerApplyEventListener( private val carerApplyEventService: CarerApplyEventService, ) { @EventListener - fun handleCarerApplyEvent(applyEvent: ApplyEvent) { - carerApplyEventService.send(applyEvent) + fun handleApplyEvent(applyEvent: ApplyEvent) { + carerApplyEventService.sendForMulticast(applyEvent) } } diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt index 61687945..4fe41ff2 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt @@ -1,6 +1,6 @@ package com.swm.idle.infrastructure.fcm.applys.service -import com.google.firebase.messaging.Message +import com.google.firebase.messaging.MulticastMessage import com.google.firebase.messaging.Notification import com.swm.idle.domain.applys.event.ApplyEvent import com.swm.idle.domain.user.common.vo.BirthYear @@ -13,9 +13,10 @@ class CarerApplyEventService( private val fcmClient: FcmClient, ) { - fun send(applyEvent: ApplyEvent) { - createMessage(applyEvent).also { - fcmClient.send(it) + + fun sendForMulticast(applyEvent: ApplyEvent) { + createMulticastMessage(applyEvent).also { + fcmClient.sendMulticast(it) } } @@ -26,7 +27,7 @@ class CarerApplyEventService( .build() } - private fun createBodyMessage(applyEvent: ApplyEvent): String? { + private fun createBodyMessage(applyEvent: ApplyEvent): String { val filteredLotNumberAddress = applyEvent.jobPosting.lotNumberAddress.split(" ") .take(3) .joinToString(" ") @@ -37,11 +38,15 @@ class CarerApplyEventService( applyEvent.jobPosting.gender.value } - private fun createMessage(applyEvent: ApplyEvent): Message { + private fun createMulticastMessage(applyEvent: ApplyEvent): MulticastMessage { val applyNotification = createApplyNotification(applyEvent) - return Message.builder() - .setToken(applyEvent.deviceToken.deviceToken) + val deviceTokens = applyEvent.deviceTokens.map { deviceToken -> + deviceToken.deviceToken + } + + return MulticastMessage.builder() + .addAllTokens(deviceTokens) .setNotification(applyNotification) .putData("destination", DestinationType.APPLICANTS.toString()) .putData("jobPostingId", applyEvent.jobPosting.id.toString()) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt index 33e5aa67..4f86eb17 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt @@ -1,19 +1,14 @@ package com.swm.idle.infrastructure.fcm.common.client import com.google.firebase.messaging.FirebaseMessaging -import com.google.firebase.messaging.Message +import com.google.firebase.messaging.MulticastMessage import org.springframework.stereotype.Component @Component class FcmClient { - fun send(message: Message) { - firebase.sendAsync(message) - } - - companion object { - - val firebase: FirebaseMessaging = FirebaseMessaging.getInstance() + fun sendMulticast(message: MulticastMessage) { + FirebaseMessaging.getInstance().sendEachForMulticast(message) } } From 0f88be5e561dfe1a748e3436f3c2e6bd89a75693 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 16 Oct 2024 17:24:54 +0900 Subject: [PATCH 052/108] =?UTF-8?q?[IDLE-415]=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=B2=98=EB=A6=AC=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/NotificationService.kt | 42 ++++++++++++++++ .../facade/NotificationFacadeService.kt | 28 +++++++++++ .../notification/enums/NotificationType.kt | 5 ++ .../domain/notification/jpa/Notification.kt | 34 +++++++++++++ .../notification/jpa/NotificationInfo.kt | 14 ++++++ .../repository/NotificationJpaRepository.kt | 8 ++++ .../notification/api/NotificationApi.kt | 48 +++++++++++++++++++ .../controller/NotificationController.kt | 17 +++++++ 8 files changed, 196 insertions(+) create mode 100644 idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt create mode 100644 idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/NotificationInfo.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt create mode 100644 idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt create mode 100644 idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt new file mode 100644 index 00000000..7f4cfe4c --- /dev/null +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt @@ -0,0 +1,42 @@ +package com.swm.idle.application.notification.domain + +import com.swm.idle.domain.common.exception.PersistenceException +import com.swm.idle.domain.notification.jpa.Notification +import com.swm.idle.domain.notification.jpa.NotificationInfo +import com.swm.idle.domain.notification.repository.NotificationJpaRepository +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.util.* + +@Service +class NotificationService( + private val notificationJpaRepository: NotificationJpaRepository, +) { + + @Transactional + fun create(notificationInfo: NotificationInfo): Notification { + return notificationJpaRepository.save( + Notification( + isRead = false, + title = notificationInfo.title, + body = notificationInfo.body, + notificationType = notificationInfo.notificationType, + receiverId = notificationInfo.receiverId, + imageUrl = notificationInfo.imageUrl, + notificationDetails = notificationInfo.notificationDetails + ) + ) + } + + fun getById(notificationId: UUID): Notification { + return notificationJpaRepository.findByIdOrNull(notificationId) + ?: throw PersistenceException.ResourceNotFound("Notification(=$notificationId) 를 찾을 수 없습니다.") + } + + @Transactional + fun read(notification: Notification) { + notification.read() + } + +} diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt new file mode 100644 index 00000000..0b863bcc --- /dev/null +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt @@ -0,0 +1,28 @@ +package com.swm.idle.application.notification.facade + +import com.swm.idle.application.common.security.getUserAuthentication +import com.swm.idle.application.notification.domain.NotificationService +import com.swm.idle.support.security.exception.SecurityException +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.util.* + +@Service +@Transactional(readOnly = true) +class NotificationFacadeService( + private val notificationService: NotificationService, +) { + + fun readNotification(notificationId: UUID) { + val notification = notificationService.getById(notificationId) + + if (notification.receiverId != getUserAuthentication().userId) { + throw SecurityException.UnAuthorizedRequest() + } + + notificationService.getById(notificationId).also { + notificationService.read(it) + } + } + +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt new file mode 100644 index 00000000..c6453e29 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt @@ -0,0 +1,5 @@ +package com.swm.idle.domain.notification.enums + +enum class NotificationType { + APPLYCANT +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/Notification.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/Notification.kt index a7793b2d..b0e285a7 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/Notification.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/Notification.kt @@ -1,8 +1,13 @@ package com.swm.idle.domain.notification.jpa +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue import com.swm.idle.domain.common.entity.BaseEntity +import com.swm.idle.domain.notification.enums.NotificationType import jakarta.persistence.Column import jakarta.persistence.Entity +import jakarta.persistence.EnumType +import jakarta.persistence.Enumerated import jakarta.persistence.Table import java.util.* @@ -13,6 +18,9 @@ class Notification( title: String, body: String, receiverId: UUID, + imageUrl: String?, + notificationType: NotificationType, + notificationDetails: Map?, ) : BaseEntity() { @Column(columnDefinition = "varchar(255)") @@ -30,4 +38,30 @@ class Notification( var receiverId: UUID = receiverId private set + @Enumerated(EnumType.STRING) + var notificationType: NotificationType = notificationType + private set + + @Column(columnDefinition = "varchar(255)") + var imageUrl: String? = imageUrl + private set + + @Column(columnDefinition = "json") + var notificationDetailsJson: String? = notificationDetails?.let { convertMapToJson(it) } + private set + + fun getNotificationDetails(): Map { + val objectMapper = jacksonObjectMapper() + return objectMapper.readValue(notificationDetailsJson.toString()) + } + + private fun convertMapToJson(details: Map): String { + val objectMapper = jacksonObjectMapper() + return objectMapper.writeValueAsString(details) + } + + fun read() { + this.isRead = true + } + } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/NotificationInfo.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/NotificationInfo.kt new file mode 100644 index 00000000..53607a77 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/jpa/NotificationInfo.kt @@ -0,0 +1,14 @@ +package com.swm.idle.domain.notification.jpa + +import com.swm.idle.domain.notification.enums.NotificationType +import java.util.* + +interface NotificationInfo { + + val title: String + val body: String + val receiverId: UUID + val notificationType: NotificationType + val imageUrl: String? + val notificationDetails: Map? +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt new file mode 100644 index 00000000..5b311f06 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt @@ -0,0 +1,8 @@ +package com.swm.idle.domain.notification.repository + +import com.swm.idle.domain.notification.jpa.Notification +import org.springframework.data.jpa.repository.JpaRepository +import java.util.* + +interface NotificationJpaRepository : JpaRepository { +} diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt new file mode 100644 index 00000000..5fd28b29 --- /dev/null +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt @@ -0,0 +1,48 @@ +package com.swm.idle.presentation.notification.api + +import com.swm.idle.presentation.common.exception.ErrorResponse +import com.swm.idle.presentation.common.security.annotation.Secured +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.media.Content +import io.swagger.v3.oas.annotations.media.Schema +import io.swagger.v3.oas.annotations.responses.ApiResponse +import io.swagger.v3.oas.annotations.responses.ApiResponses +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.http.HttpStatus +import org.springframework.web.bind.annotation.PatchMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.ResponseStatus +import java.util.* + +@Tag(name = "Notification", description = "알림 API") +@RequestMapping("/api/v1/notifications", produces = ["application/json;charset=utf-8"]) +interface NotificationApi { + + @Secured + @Operation(summary = "알림 읽음 처리 API") + @PatchMapping("/{notification-id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + @ApiResponses( + value = [ + ApiResponse( + responseCode = "204", + description = "처리 성공", + ), + ApiResponse( + responseCode = "400", + description = "처리 실패 - 본인이 아닌, 인증되지 않은 사용자가 읽음 처리를 시도한 경우", + content = [ + Content( + mediaType = "application/json", + schema = Schema( + implementation = ErrorResponse::class + ) + ), + ] + ), + ] + ) + fun readNotification(@PathVariable("notification-id") notificationId: UUID) + +} diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt new file mode 100644 index 00000000..2ce500d3 --- /dev/null +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt @@ -0,0 +1,17 @@ +package com.swm.idle.presentation.notification.controller + +import com.swm.idle.application.notification.facade.NotificationFacadeService +import com.swm.idle.presentation.notification.api.NotificationApi +import org.springframework.web.bind.annotation.RestController +import java.util.* + +@RestController +class NotificationController( + private val notificationFacadeService: NotificationFacadeService, +) : NotificationApi { + + override fun readNotification(notificationId: UUID) { + notificationFacadeService.readNotification(notificationId) + } + +} From 6f185c2b5c5aac32c26c204ddf00af687479c7b2 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 18 Oct 2024 14:52:15 +0900 Subject: [PATCH 053/108] =?UTF-8?q?[IDLE-417]=20=EC=9D=BD=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EC=9D=80=20=EC=95=8C=EB=A6=BC=20=EC=88=98=20=EC=A7=91?= =?UTF-8?q?=EA=B3=84=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/domain/NotificationService.kt | 4 ++++ .../notification/facade/NotificationFacadeService.kt | 11 +++++++++++ .../domain/notification/enums/NotificationType.kt | 2 +- .../repository/NotificationJpaRepository.kt | 12 ++++++++++++ .../presentation/notification/api/NotificationApi.kt | 8 ++++++++ .../controller/NotificationController.kt | 5 +++++ .../notification/UnreadNotificationCountResponse.kt | 5 +++++ 7 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/UnreadNotificationCountResponse.kt diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt index 7f4cfe4c..13382ded 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt @@ -39,4 +39,8 @@ class NotificationService( notification.read() } + fun countUnreadNotificationByUserId(userId: UUID): Int { + return notificationJpaRepository.countByUserIdWithUnreadStatus(userId) + } + } diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt index 0b863bcc..a911ee67 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt @@ -3,6 +3,7 @@ package com.swm.idle.application.notification.facade import com.swm.idle.application.common.security.getUserAuthentication import com.swm.idle.application.notification.domain.NotificationService import com.swm.idle.support.security.exception.SecurityException +import com.swm.idle.support.transfer.notification.UnreadNotificationCountResponse import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.util.* @@ -25,4 +26,14 @@ class NotificationFacadeService( } } + fun countUnreadNotification(): UnreadNotificationCountResponse { + val userId = getUserAuthentication().userId + + return notificationService.countUnreadNotificationByUserId(userId).let { + UnreadNotificationCountResponse( + unreadNotificationCount = it + ) + } + } + } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt index c6453e29..567db68f 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt @@ -1,5 +1,5 @@ package com.swm.idle.domain.notification.enums enum class NotificationType { - APPLYCANT + APPLICANT } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt index 5b311f06..2fa44fc2 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt @@ -2,7 +2,19 @@ package com.swm.idle.domain.notification.repository import com.swm.idle.domain.notification.jpa.Notification import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query import java.util.* interface NotificationJpaRepository : JpaRepository { + + @Query( + """ + SELECT COUNT(*) + FROM notification + WHERE notification.receiver_id = :userId + AND notification.is_read = false + """, + nativeQuery = true + ) + fun countByUserIdWithUnreadStatus(userId: UUID): Int } diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt index 5fd28b29..9baf17ac 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt @@ -2,6 +2,7 @@ package com.swm.idle.presentation.notification.api import com.swm.idle.presentation.common.exception.ErrorResponse import com.swm.idle.presentation.common.security.annotation.Secured +import com.swm.idle.support.transfer.notification.UnreadNotificationCountResponse import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.media.Content import io.swagger.v3.oas.annotations.media.Schema @@ -9,6 +10,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.responses.ApiResponses import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.http.HttpStatus +import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PatchMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RequestMapping @@ -45,4 +47,10 @@ interface NotificationApi { ) fun readNotification(@PathVariable("notification-id") notificationId: UUID) + @Secured + @Operation(summary = "읽지 않은 알림 수 집계 API") + @GetMapping("/count") + @ResponseStatus(HttpStatus.OK) + fun countUnreadNotification(): UnreadNotificationCountResponse + } diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt index 2ce500d3..8cdd2379 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt @@ -2,6 +2,7 @@ package com.swm.idle.presentation.notification.controller import com.swm.idle.application.notification.facade.NotificationFacadeService import com.swm.idle.presentation.notification.api.NotificationApi +import com.swm.idle.support.transfer.notification.UnreadNotificationCountResponse import org.springframework.web.bind.annotation.RestController import java.util.* @@ -14,4 +15,8 @@ class NotificationController( notificationFacadeService.readNotification(notificationId) } + override fun countUnreadNotification(): UnreadNotificationCountResponse { + return notificationFacadeService.countUnreadNotification() + } + } diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/UnreadNotificationCountResponse.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/UnreadNotificationCountResponse.kt new file mode 100644 index 00000000..995ed12d --- /dev/null +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/UnreadNotificationCountResponse.kt @@ -0,0 +1,5 @@ +package com.swm.idle.support.transfer.notification + +data class UnreadNotificationCountResponse( + val unreadNotificationCount: Int, +) From eaa9122bfc7d1931a9163f6cd45542f2f41c2d65 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Sat, 19 Oct 2024 12:42:30 +0900 Subject: [PATCH 054/108] =?UTF-8?q?[IDLE-418]=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/NotificationService.kt | 17 +++++- .../facade/NotificationFacadeService.kt | 56 +++++++++++++++++++ .../converter/NotificationDetailsConverter.kt | 16 ++++++ .../domain/common/dto/NotificationQueryDto.kt | 16 ++++++ .../{ => jpa}/NotificationJpaRepository.kt | 2 +- .../querydsl/NotificationQueryRepository.kt | 46 +++++++++++++++ .../notification/api/NotificationApi.kt | 8 +++ .../controller/NotificationController.kt | 6 ++ .../NotificationScrollResponse.kt | 49 ++++++++++++++++ 9 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 idle-application/src/main/kotlin/com/swm/idle/application/notification/utils/converter/NotificationDetailsConverter.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/NotificationQueryDto.kt rename idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/{ => jpa}/NotificationJpaRepository.kt (90%) create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt create mode 100644 idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/NotificationScrollResponse.kt diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt index 13382ded..f777baf1 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/NotificationService.kt @@ -1,9 +1,11 @@ package com.swm.idle.application.notification.domain +import com.swm.idle.domain.common.dto.NotificationQueryDto import com.swm.idle.domain.common.exception.PersistenceException import com.swm.idle.domain.notification.jpa.Notification import com.swm.idle.domain.notification.jpa.NotificationInfo -import com.swm.idle.domain.notification.repository.NotificationJpaRepository +import com.swm.idle.domain.notification.repository.jpa.NotificationJpaRepository +import com.swm.idle.domain.notification.repository.querydsl.NotificationQueryRepository import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -12,6 +14,7 @@ import java.util.* @Service class NotificationService( private val notificationJpaRepository: NotificationJpaRepository, + private val notificationQueryRepository: NotificationQueryRepository, ) { @Transactional @@ -43,4 +46,16 @@ class NotificationService( return notificationJpaRepository.countByUserIdWithUnreadStatus(userId) } + fun findAllByUserId( + next: UUID?, + limit: Long, + userId: UUID, + ): List { + return notificationQueryRepository.findAllByUserId( + next = next, + limit = limit, + userId = userId, + ) + } + } diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt index a911ee67..c8f048c1 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt @@ -2,7 +2,11 @@ package com.swm.idle.application.notification.facade import com.swm.idle.application.common.security.getUserAuthentication import com.swm.idle.application.notification.domain.NotificationService +import com.swm.idle.application.notification.utils.converter.NotificationDetailsConverter +import com.swm.idle.domain.common.dto.NotificationQueryDto import com.swm.idle.support.security.exception.SecurityException +import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest +import com.swm.idle.support.transfer.notification.NotificationScrollResponse import com.swm.idle.support.transfer.notification.UnreadNotificationCountResponse import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -12,6 +16,7 @@ import java.util.* @Transactional(readOnly = true) class NotificationFacadeService( private val notificationService: NotificationService, + private val notificationDetailsConverter: NotificationDetailsConverter, ) { fun readNotification(notificationId: UUID) { @@ -36,4 +41,55 @@ class NotificationFacadeService( } } + fun getNotifications(request: CursorScrollRequest): NotificationScrollResponse { + val userId = getUserAuthentication().userId + + val (items, next) = scrollByUser( + userId = userId, + next = request.next, + limit = request.limit, + ) + + return NotificationScrollResponse.from( + items = items.map { notificationQueryDto -> + NotificationScrollResponse.NotificationDto( + id = notificationQueryDto.id, + isRead = notificationQueryDto.isRead, + title = notificationQueryDto.title, + body = notificationQueryDto.body, + notificationType = notificationQueryDto.notificationType, + createdAt = notificationQueryDto.createdAt, + imageUrl = notificationQueryDto.imageUrl, + notificationDetails = notificationDetailsConverter.convertToMap( + notificationQueryDto.notificationDetails + ) // map으로 변환 + ) + }, + next = next, + total = items.size + ) + } + + private fun scrollByUser( + userId: UUID, + next: UUID?, + limit: Long, + ): Pair, UUID?> { + + val notificationDtos = notificationService.findAllByUserId( + next = next, + limit = limit + 1, + userId = userId, + ) + + val newNext = + if (notificationDtos.size > limit) notificationDtos.last().id else null + val items = + if (newNext == null) notificationDtos else notificationDtos.subList( + 0, + limit.toInt() + ) + return items to newNext + } + } diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/utils/converter/NotificationDetailsConverter.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/utils/converter/NotificationDetailsConverter.kt new file mode 100644 index 00000000..b2dc5e27 --- /dev/null +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/utils/converter/NotificationDetailsConverter.kt @@ -0,0 +1,16 @@ +package com.swm.idle.application.notification.utils.converter + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import org.springframework.stereotype.Component + +@Component +class NotificationDetailsConverter { + + private val objectMapper: ObjectMapper = ObjectMapper() + + fun convertToMap(details: String): Map { + return objectMapper.readValue(details) + } + +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/NotificationQueryDto.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/NotificationQueryDto.kt new file mode 100644 index 00000000..b0b9a26b --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/NotificationQueryDto.kt @@ -0,0 +1,16 @@ +package com.swm.idle.domain.common.dto + +import com.swm.idle.domain.notification.enums.NotificationType +import java.time.LocalDateTime +import java.util.* + +data class NotificationQueryDto( + val id: UUID, + val isRead: Boolean, + val title: String, + val body: String, + val notificationType: NotificationType, + val createdAt: LocalDateTime, + val imageUrl: String?, + var notificationDetails: String, +) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/jpa/NotificationJpaRepository.kt similarity index 90% rename from idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt rename to idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/jpa/NotificationJpaRepository.kt index 2fa44fc2..83a38a7e 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/NotificationJpaRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/jpa/NotificationJpaRepository.kt @@ -1,4 +1,4 @@ -package com.swm.idle.domain.notification.repository +package com.swm.idle.domain.notification.repository.jpa import com.swm.idle.domain.notification.jpa.Notification import org.springframework.data.jpa.repository.JpaRepository diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt new file mode 100644 index 00000000..0b4dc2c2 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt @@ -0,0 +1,46 @@ +package com.swm.idle.domain.notification.repository.querydsl + +import com.querydsl.core.types.Projections +import com.querydsl.jpa.impl.JPAQueryFactory +import com.swm.idle.domain.common.dto.NotificationQueryDto +import com.swm.idle.domain.common.enums.EntityStatus +import com.swm.idle.domain.notification.jpa.QNotification.notification +import org.springframework.stereotype.Repository +import java.util.* + +@Repository +class NotificationQueryRepository( + private val jpaQueryFactory: JPAQueryFactory, +) { + + fun findAllByUserId( + next: UUID?, + limit: Long, + userId: UUID, + ): List { + return jpaQueryFactory + .select( + Projections.constructor( + NotificationQueryDto::class.java, + notification.id, + notification.isRead, + notification.title, + notification.body, + notification.notificationType, + notification.createdAt, + notification.imageUrl, + notification.notificationDetailsJson + ) + ) + .from(notification) + .where( + notification.receiverId.eq(userId) + .and(next?.let { notification.id.goe(it) }) + .and(notification.entityStatus.eq(EntityStatus.ACTIVE)) + ) + .orderBy(notification.createdAt.desc()) + .limit(limit) + .fetch() + } + +} diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt index 9baf17ac..a385baf6 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt @@ -2,6 +2,8 @@ package com.swm.idle.presentation.notification.api import com.swm.idle.presentation.common.exception.ErrorResponse import com.swm.idle.presentation.common.security.annotation.Secured +import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest +import com.swm.idle.support.transfer.notification.NotificationScrollResponse import com.swm.idle.support.transfer.notification.UnreadNotificationCountResponse import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.media.Content @@ -53,4 +55,10 @@ interface NotificationApi { @ResponseStatus(HttpStatus.OK) fun countUnreadNotification(): UnreadNotificationCountResponse + @Secured + @Operation(summary = "알림 전체 조회 API") + @GetMapping("/my") + @ResponseStatus(HttpStatus.OK) + fun getNotifications(request: CursorScrollRequest): NotificationScrollResponse + } diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt index 8cdd2379..a325202a 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt @@ -2,6 +2,8 @@ package com.swm.idle.presentation.notification.controller import com.swm.idle.application.notification.facade.NotificationFacadeService import com.swm.idle.presentation.notification.api.NotificationApi +import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest +import com.swm.idle.support.transfer.notification.NotificationScrollResponse import com.swm.idle.support.transfer.notification.UnreadNotificationCountResponse import org.springframework.web.bind.annotation.RestController import java.util.* @@ -19,4 +21,8 @@ class NotificationController( return notificationFacadeService.countUnreadNotification() } + override fun getNotifications(request: CursorScrollRequest): NotificationScrollResponse { + return notificationFacadeService.getNotifications(request) + } + } diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/NotificationScrollResponse.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/NotificationScrollResponse.kt new file mode 100644 index 00000000..5b1b60c2 --- /dev/null +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/NotificationScrollResponse.kt @@ -0,0 +1,49 @@ +package com.swm.idle.support.transfer.notification + +import com.swm.idle.domain.notification.enums.NotificationType +import com.swm.idle.support.transfer.common.ScrollResponse +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime +import java.util.* + +@Schema( + name = "NotificationScrollResponse", + description = "알림 전체 조회 페이징 응답", +) +data class NotificationScrollResponse( + override val items: List, + override val next: UUID?, + override val total: Int, +) : ScrollResponse( + items = items, + next = next, + total = total, +) { + + data class NotificationDto( + val id: UUID, + val isRead: Boolean, + val title: String, + val body: String, + val notificationType: NotificationType, + val createdAt: LocalDateTime, + val imageUrl: String?, + var notificationDetails: Map, + ) + + companion object { + + fun from( + items: List, + next: UUID?, + total: Int, + ): NotificationScrollResponse { + return NotificationScrollResponse( + items = items, + next = next, + total = total, + ) + } + } + +} From 83d0c6977e99284670ca2fa93ec0c47389bc3168 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Sat, 19 Oct 2024 13:02:09 +0900 Subject: [PATCH 055/108] =?UTF-8?q?[IDLE-418]=20=ED=94=BC=EB=93=9C?= =?UTF-8?q?=EB=B0=B1=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jobposting/facade/CarerJobPostingFacadeService.kt | 2 +- .../jobposting/facade/CrawlingJobPostingFacadeService.kt | 2 +- .../idle/application/notification/domain/DeviceTokenService.kt | 2 +- .../notification/facade/NotificationFacadeService.kt | 2 +- .../com/swm/idle/domain/common/dto/NotificationQueryDto.kt | 2 +- .../repository/{ => jpa}/DeviceTokenJpaRepository.kt | 2 +- .../swm/idle/presentation/jobposting/api/CarerJobPostingApi.kt | 2 +- .../idle/presentation/jobposting/api/CrawlingJobPostingApi.kt | 2 +- .../jobposting/controller/CarerJobPostingController.kt | 2 +- .../jobposting/controller/CrawlingJobPostingController.kt | 2 +- .../swm/idle/presentation/notification/api/NotificationApi.kt | 2 +- .../notification/controller/NotificationController.kt | 2 +- .../{jobposting/carer => common}/CursorScrollRequest.kt | 3 +-- .../transfer/notification/NotificationScrollResponse.kt | 2 +- 14 files changed, 14 insertions(+), 15 deletions(-) rename idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/{ => jpa}/DeviceTokenJpaRepository.kt (88%) rename idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/{jobposting/carer => common}/CursorScrollRequest.kt (81%) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CarerJobPostingFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CarerJobPostingFacadeService.kt index a23613bb..aed5b300 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CarerJobPostingFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CarerJobPostingFacadeService.kt @@ -13,10 +13,10 @@ import com.swm.idle.application.user.center.service.domain.CenterService import com.swm.idle.domain.common.dto.JobPostingPreviewDto import com.swm.idle.domain.common.enums.EntityStatus import com.swm.idle.domain.user.carer.entity.jpa.Carer +import com.swm.idle.support.transfer.common.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.carer.CarerAppliedJobPostingScrollResponse import com.swm.idle.support.transfer.jobposting.carer.CarerJobPostingResponse import com.swm.idle.support.transfer.jobposting.carer.CarerJobPostingScrollResponse -import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.carer.JobPostingFavoriteResponse import org.locationtech.jts.geom.Point import org.springframework.stereotype.Service diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt index b130de4b..cf72c638 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/CrawlingJobPostingFacadeService.kt @@ -8,9 +8,9 @@ import com.swm.idle.application.user.carer.domain.CarerService import com.swm.idle.domain.common.dto.CrawlingJobPostingPreviewDto import com.swm.idle.domain.user.carer.entity.jpa.Carer import com.swm.idle.infrastructure.client.geocode.service.GeoCodeService +import com.swm.idle.support.transfer.common.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.carer.CrawlingJobPostingFavoriteResponse import com.swm.idle.support.transfer.jobposting.carer.CrawlingJobPostingScrollResponse -import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.common.CrawlingJobPostingResponse import org.locationtech.jts.geom.Point import org.springframework.stereotype.Service diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt index 3d0a35bd..f4674f3b 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt @@ -1,7 +1,7 @@ package com.swm.idle.application.notification.domain import com.swm.idle.domain.notification.jpa.DeviceToken -import com.swm.idle.domain.notification.repository.DeviceTokenJpaRepository +import com.swm.idle.domain.notification.repository.jpa.DeviceTokenJpaRepository import com.swm.idle.domain.user.common.enum.UserType import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt index c8f048c1..a4d7f648 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt @@ -5,7 +5,7 @@ import com.swm.idle.application.notification.domain.NotificationService import com.swm.idle.application.notification.utils.converter.NotificationDetailsConverter import com.swm.idle.domain.common.dto.NotificationQueryDto import com.swm.idle.support.security.exception.SecurityException -import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest +import com.swm.idle.support.transfer.common.CursorScrollRequest import com.swm.idle.support.transfer.notification.NotificationScrollResponse import com.swm.idle.support.transfer.notification.UnreadNotificationCountResponse import org.springframework.stereotype.Service diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/NotificationQueryDto.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/NotificationQueryDto.kt index b0b9a26b..a9c028bd 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/NotificationQueryDto.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/common/dto/NotificationQueryDto.kt @@ -12,5 +12,5 @@ data class NotificationQueryDto( val notificationType: NotificationType, val createdAt: LocalDateTime, val imageUrl: String?, - var notificationDetails: String, + val notificationDetails: String, ) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/jpa/DeviceTokenJpaRepository.kt similarity index 88% rename from idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt rename to idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/jpa/DeviceTokenJpaRepository.kt index 62aaf96c..7ecba361 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/DeviceTokenJpaRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/jpa/DeviceTokenJpaRepository.kt @@ -1,4 +1,4 @@ -package com.swm.idle.domain.notification.repository +package com.swm.idle.domain.notification.repository.jpa import com.swm.idle.domain.notification.jpa.DeviceToken import org.springframework.data.jpa.repository.JpaRepository diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/api/CarerJobPostingApi.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/api/CarerJobPostingApi.kt index d09547ff..34b76a96 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/api/CarerJobPostingApi.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/api/CarerJobPostingApi.kt @@ -1,11 +1,11 @@ package com.swm.idle.presentation.jobposting.api import com.swm.idle.presentation.common.security.annotation.Secured +import com.swm.idle.support.transfer.common.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.carer.CarerAppliedJobPostingScrollResponse import com.swm.idle.support.transfer.jobposting.carer.CarerJobPostingResponse import com.swm.idle.support.transfer.jobposting.carer.CarerJobPostingScrollResponse import com.swm.idle.support.transfer.jobposting.carer.CreateJobPostingFavoriteRequest -import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.carer.JobPostingFavoriteResponse import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/api/CrawlingJobPostingApi.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/api/CrawlingJobPostingApi.kt index 541136c5..ec6b29ae 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/api/CrawlingJobPostingApi.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/api/CrawlingJobPostingApi.kt @@ -1,9 +1,9 @@ package com.swm.idle.presentation.jobposting.api import com.swm.idle.presentation.common.security.annotation.Secured +import com.swm.idle.support.transfer.common.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.carer.CrawlingJobPostingFavoriteResponse import com.swm.idle.support.transfer.jobposting.carer.CrawlingJobPostingScrollResponse -import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.common.CrawlingJobPostingResponse import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/controller/CarerJobPostingController.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/controller/CarerJobPostingController.kt index 7d50cb52..2f97c9a8 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/controller/CarerJobPostingController.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/controller/CarerJobPostingController.kt @@ -6,11 +6,11 @@ import com.swm.idle.application.jobposting.facade.CarerJobPostingFacadeService import com.swm.idle.application.jobposting.facade.JobPostingFavoriteFacadeService import com.swm.idle.application.user.carer.domain.CarerService import com.swm.idle.presentation.jobposting.api.CarerJobPostingApi +import com.swm.idle.support.transfer.common.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.carer.CarerAppliedJobPostingScrollResponse import com.swm.idle.support.transfer.jobposting.carer.CarerJobPostingResponse import com.swm.idle.support.transfer.jobposting.carer.CarerJobPostingScrollResponse import com.swm.idle.support.transfer.jobposting.carer.CreateJobPostingFavoriteRequest -import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.carer.JobPostingFavoriteResponse import org.springframework.web.bind.annotation.RestController import java.util.* diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/controller/CrawlingJobPostingController.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/controller/CrawlingJobPostingController.kt index 47ecdc91..98b5e2c0 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/controller/CrawlingJobPostingController.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/jobposting/controller/CrawlingJobPostingController.kt @@ -5,9 +5,9 @@ import com.swm.idle.application.common.security.getUserAuthentication import com.swm.idle.application.jobposting.facade.CrawlingJobPostingFacadeService import com.swm.idle.application.user.carer.domain.CarerService import com.swm.idle.presentation.jobposting.api.CrawlingJobPostingApi +import com.swm.idle.support.transfer.common.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.carer.CrawlingJobPostingFavoriteResponse import com.swm.idle.support.transfer.jobposting.carer.CrawlingJobPostingScrollResponse -import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest import com.swm.idle.support.transfer.jobposting.common.CrawlingJobPostingResponse import org.springframework.web.bind.annotation.RestController import java.util.* diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt index a385baf6..80623fb4 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/api/NotificationApi.kt @@ -2,7 +2,7 @@ package com.swm.idle.presentation.notification.api import com.swm.idle.presentation.common.exception.ErrorResponse import com.swm.idle.presentation.common.security.annotation.Secured -import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest +import com.swm.idle.support.transfer.common.CursorScrollRequest import com.swm.idle.support.transfer.notification.NotificationScrollResponse import com.swm.idle.support.transfer.notification.UnreadNotificationCountResponse import io.swagger.v3.oas.annotations.Operation diff --git a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt index a325202a..7eaa76d6 100644 --- a/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt +++ b/idle-presentation/src/main/kotlin/com/swm/idle/presentation/notification/controller/NotificationController.kt @@ -2,7 +2,7 @@ package com.swm.idle.presentation.notification.controller import com.swm.idle.application.notification.facade.NotificationFacadeService import com.swm.idle.presentation.notification.api.NotificationApi -import com.swm.idle.support.transfer.jobposting.carer.CursorScrollRequest +import com.swm.idle.support.transfer.common.CursorScrollRequest import com.swm.idle.support.transfer.notification.NotificationScrollResponse import com.swm.idle.support.transfer.notification.UnreadNotificationCountResponse import org.springframework.web.bind.annotation.RestController diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CursorScrollRequest.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/common/CursorScrollRequest.kt similarity index 81% rename from idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CursorScrollRequest.kt rename to idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/common/CursorScrollRequest.kt index 86f2e46c..19aac98c 100644 --- a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/jobposting/carer/CursorScrollRequest.kt +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/common/CursorScrollRequest.kt @@ -1,6 +1,5 @@ -package com.swm.idle.support.transfer.jobposting.carer +package com.swm.idle.support.transfer.common -import com.swm.idle.support.transfer.common.ScrollRequest import io.swagger.v3.oas.annotations.Parameter import org.springdoc.core.annotations.ParameterObject import java.util.* diff --git a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/NotificationScrollResponse.kt b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/NotificationScrollResponse.kt index 5b1b60c2..05201e58 100644 --- a/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/NotificationScrollResponse.kt +++ b/idle-support/transfer/src/main/kotlin/com/swm/idle/support/transfer/notification/NotificationScrollResponse.kt @@ -28,7 +28,7 @@ data class NotificationScrollResponse( val notificationType: NotificationType, val createdAt: LocalDateTime, val imageUrl: String?, - var notificationDetails: Map, + val notificationDetails: Map, ) companion object { From bd9ce68d7e2f14cbd8570276e5a223db4e1b879f Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Sat, 19 Oct 2024 15:42:05 +0900 Subject: [PATCH 056/108] =?UTF-8?q?[IDLE-423]=20soft-delete=EA=B0=80=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=EB=90=9C=20=EC=A6=90=EA=B2=A8=EC=B0=BE?= =?UTF-8?q?=EA=B8=B0=20entity=EC=97=90=EC=84=9C,=20=EC=A6=90=EA=B2=A8?= =?UTF-8?q?=EC=B0=BE=EA=B8=B0=20=ED=95=B4=EC=A0=9C=20=ED=9B=84=20=EB=8B=A4?= =?UTF-8?q?=EC=8B=9C=20=EC=84=A4=EC=A0=95=ED=95=98=EB=8A=94=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=EB=A5=BC=20=ED=95=B4=EA=B2=B0=ED=95=9C=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jobposting/facade/JobPostingFavoriteFacadeService.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/JobPostingFavoriteFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/JobPostingFavoriteFacadeService.kt index bfaa847b..90daca5f 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/JobPostingFavoriteFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/JobPostingFavoriteFacadeService.kt @@ -19,7 +19,12 @@ data class JobPostingFavoriteFacadeService( carerId: UUID, jobPostingType: JobPostingType, ) { - jobPostingFavoriteService.create( + jobPostingFavoriteService.findByJobPostingIdAndCarerId( + jobPostingId = jobPostingId, + carerId = carerId, + )?.let { + it.active() + } ?: jobPostingFavoriteService.create( jobPostingId = jobPostingId, carerId = carerId, jobPostingType = jobPostingType, From 6d967a9342a73a01ce7c2688c31e3cf960c4b27d Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Sat, 19 Oct 2024 16:18:00 +0900 Subject: [PATCH 057/108] =?UTF-8?q?[IDLE-424]=20=EC=9A=94=EC=96=91=20?= =?UTF-8?q?=EB=B3=B4=ED=98=B8=EC=82=AC=20=EA=B3=B5=EA=B3=A0=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C,=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=EB=90=9C=20=EA=B3=B5=EA=B3=A0=EA=B0=80=20=ED=95=A8?= =?UTF-8?q?=EA=BB=98=20=EB=B3=B4=EC=9D=B4=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jobposting/repository/querydsl/JobPostingQueryRepository.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingQueryRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingQueryRepository.kt index e5068445..4136cabf 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingQueryRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingQueryRepository.kt @@ -30,6 +30,7 @@ class JobPostingQueryRepository( .where( applys.carerId.eq(carerId) .and(next?.let { jobPosting.id.goe(it) }) + .and(jobPosting.entityStatus.eq(EntityStatus.ACTIVE)) ) .limit(limit) .fetch() From 4fde52b0c1fcd8bcfdfd1db0254d3d9fc98492c9 Mon Sep 17 00:00:00 2001 From: Wonjun You <59856002+wonjunYou@users.noreply.github.com> Date: Sun, 20 Oct 2024 00:53:32 +0900 Subject: [PATCH 058/108] =?UTF-8?q?[IDLE-400]=20=EC=B1=84=EC=9A=A9=20?= =?UTF-8?q?=EA=B3=B5=EA=B3=A0=20=EC=A7=80=EC=9B=90=EC=9E=90=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=20=EC=8B=9C,=20=EC=84=BC=ED=84=B0=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=EC=9E=90=EC=97=90=EA=B2=8C=20=EC=95=8C=EB=A6=BC?= =?UTF-8?q?=EC=9D=84=20=EB=B0=9C=EC=86=A1=ED=95=9C=EB=8B=A4.=20(#183)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [IDLE-400] 채용 공고 지원자 발생 시, 센터 관리자에게 알림을 발송한다. * [IDLE-400] fcm 모듈 설정 추가 * [IDLE-400] 공고 지원자 발생 시, 모든 센터 관리자들에게 다중 알림을 발송한다. * [IDLE-400] 채용 공고 지원자 발생 시, 센터 관리자에게 알림을 발송한다. * [IDLE-400] fcm 모듈 설정 추가 * [IDLE-400] 공고 지원자 발생 시, 모든 센터 관리자들에게 다중 알림을 발송한다. * [IDLE-415] 알림 조회 처리 API * [IDLE-417] 읽지 않은 알림 수 집계 API * [IDLE-418] 알림 목록 조회 API * [IDLE-418] 피드백 반영 * [IDLE-423] soft-delete가 적용된 즐겨찾기 entity에서, 즐겨찾기 해제 후 다시 설정하는 경우 발생하는 버그를 해결한다. * [IDLE-424] 요양 보호사 공고 전체 조회 시, 삭제된 공고가 함께 보이는 문제 해결 * [IDLE-400] 알림 명세 변경 * [IDLE-400] fcm 설정 파일 디렉토리 path 변경 * [IDLE-400] ddl 옵션 변경 * [IDLE-400] ci/cd 옵션 변경 --- .github/workflows/dev-server-deployer.yaml | 6 +- .github/workflows/dev-server-integrator.yaml | 2 +- .github/workflows/prod-server-deployer.yaml | 4 +- .../applys/facade/CarerApplyFacadeService.kt | 68 +++++++++++++------ .../applys/vo/CarerApplyNotificationInfo.kt | 41 +++++++++++ .../idle/domain/applys/event/ApplyEvent.kt | 18 ++--- .../notification/enums/NotificationType.kt | 2 +- .../src/main/resources/application-domain.yml | 2 +- .../listener/CarerApplyEventListener.kt | 2 +- .../applys/service/CarerApplyEventService.kt | 49 ++++++------- .../fcm/common/client/FcmClient.kt | 6 +- .../src/main/resources/application-fcm.yml | 2 +- 12 files changed, 131 insertions(+), 71 deletions(-) create mode 100644 idle-application/src/main/kotlin/com/swm/idle/application/applys/vo/CarerApplyNotificationInfo.kt diff --git a/.github/workflows/dev-server-deployer.yaml b/.github/workflows/dev-server-deployer.yaml index a042e3bf..9f7febf2 100644 --- a/.github/workflows/dev-server-deployer.yaml +++ b/.github/workflows/dev-server-deployer.yaml @@ -44,9 +44,9 @@ jobs: --cidr ${{ steps.publicip.outputs.ip }}/32 - name: Set Up Firebase Service Key - run : | - mkdir ./src/main/resources/firebase - echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > ./src/main/resources/firebase/adminkey.json + run: | + mkdir ./idle-infrastructure/fcm/src/main/resources/firebase + echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > /idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json - name: Copy Docker Compose file to server uses: appleboy/scp-action@master diff --git a/.github/workflows/dev-server-integrator.yaml b/.github/workflows/dev-server-integrator.yaml index 0cf1cc65..c43e997f 100644 --- a/.github/workflows/dev-server-integrator.yaml +++ b/.github/workflows/dev-server-integrator.yaml @@ -3,7 +3,7 @@ name: Develop Server Integrator (CI) on: push: branches: - - develop + - feat/IDLE-400 jobs: build_and_push: diff --git a/.github/workflows/prod-server-deployer.yaml b/.github/workflows/prod-server-deployer.yaml index 60fa9612..0bb2be04 100644 --- a/.github/workflows/prod-server-deployer.yaml +++ b/.github/workflows/prod-server-deployer.yaml @@ -75,8 +75,8 @@ jobs: - name: Set Up Firebase Service Key run: | - mkdir ./idle-infrastructure/fcm/main/resources/firebase - echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > /idle-infrastructure/fcm/main/resources/firebase/adminkey.json + mkdir ./idle-infrastructure/fcm/src/main/resources/firebase + echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > ./idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json - name: Run Docker uses: appleboy/ssh-action@master diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt index f1904e9b..6af2e8ba 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt @@ -2,19 +2,23 @@ package com.swm.idle.application.applys.facade import com.swm.idle.application.applys.domain.CarerApplyEventPublisher import com.swm.idle.application.applys.domain.CarerApplyService +import com.swm.idle.application.applys.vo.CarerApplyNotificationInfo import com.swm.idle.application.common.security.getUserAuthentication import com.swm.idle.application.jobposting.domain.JobPostingService import com.swm.idle.application.notification.domain.DeviceTokenService +import com.swm.idle.application.notification.domain.NotificationService import com.swm.idle.application.user.carer.domain.CarerService import com.swm.idle.application.user.center.service.domain.CenterManagerService import com.swm.idle.application.user.center.service.domain.CenterService import com.swm.idle.domain.applys.event.ApplyEvent import com.swm.idle.domain.applys.exception.ApplyException import com.swm.idle.domain.common.enums.EntityStatus +import com.swm.idle.domain.jobposting.entity.jpa.JobPosting import com.swm.idle.domain.jobposting.enums.ApplyMethodType +import com.swm.idle.domain.notification.enums.NotificationType import com.swm.idle.domain.user.center.enums.CenterManagerAccountStatus import com.swm.idle.domain.user.center.vo.BusinessRegistrationNumber -import io.github.oshai.kotlinlogging.KotlinLogging +import com.swm.idle.domain.user.common.vo.BirthYear import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Propagation import org.springframework.transaction.annotation.Transactional @@ -30,10 +34,9 @@ class CarerApplyFacadeService( private val carerService: CarerService, private val centerManagerService: CenterManagerService, private val centerService: CenterService, + private val notificationService: NotificationService, ) { - private val logger = KotlinLogging.logger { } - @Transactional(propagation = Propagation.REQUIRES_NEW) fun createApply( jobPostingId: UUID, @@ -48,28 +51,51 @@ class CarerApplyFacadeService( throw ApplyException.AlreadyApplied() } - val center = centerService.getById(jobPosting.centerId) - - val deviceTokens = centerManagerService.findAllByCenterBusinessRegistrationNumber( - BusinessRegistrationNumber(center.businessRegistrationNumber) - )?.filter { centerManager -> - centerManager.status == CenterManagerAccountStatus.APPROVED && centerManager.entityStatus == EntityStatus.ACTIVE - }?.mapNotNull { centerManager -> - deviceTokenService.findByUserId(centerManager.id) + val centerManagers = centerService.getById(jobPosting.centerId).let { + centerManagerService.findAllByCenterBusinessRegistrationNumber( + BusinessRegistrationNumber(it.businessRegistrationNumber) + )?.filter { centerManager -> + centerManager.status == CenterManagerAccountStatus.APPROVED && centerManager.entityStatus == EntityStatus.ACTIVE + } } - deviceTokens?.let { - ApplyEvent.createApplyEvent( - deviceTokens = deviceTokens, - jobPosting = jobPosting, - carer = carer, - ).also { - carerApplyEventPublisher.publish(it) + centerManagers?.map { centerManager -> + val deviceToken = deviceTokenService.findByUserId(centerManager.id) + + if (deviceToken != null) { + val notificationInfo = CarerApplyNotificationInfo( + title = "${carer.name} 님이 공고에 지원하였습니다.", + body = createBodyMessage(jobPosting), + receiverId = centerManager.id, + notificationType = NotificationType.APPLICANT, + imageUrl = carer.profileImageUrl, + notificationDetails = mapOf( + "jobPostingId" to jobPostingId, + ) + ) + + val notification = notificationService.create(notificationInfo) + + ApplyEvent.createApplyEvent( + deviceToken = deviceToken, + notificationId = notification.id, + notificationInfo = notificationInfo + ).also { + carerApplyEventPublisher.publish(it) + } } - } ?: run { - logger.warn { "device Token이 존재하지 않아 알림이 발송되지 않았습니다." } } - carerApplyService.create(jobPostingId, carer.id, applyMethodType) } + + private fun createBodyMessage(jobPosting: JobPosting): String { + val filteredLotNumberAddress = jobPosting.lotNumberAddress.split(" ") + .take(3) + .joinToString(" ") + + return "$filteredLotNumberAddress " + + "${jobPosting.careLevel}등급 " + + "${BirthYear.calculateAge(jobPosting.birthYear)}세 " + + jobPosting.gender.value + } } diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/applys/vo/CarerApplyNotificationInfo.kt b/idle-application/src/main/kotlin/com/swm/idle/application/applys/vo/CarerApplyNotificationInfo.kt new file mode 100644 index 00000000..3609c131 --- /dev/null +++ b/idle-application/src/main/kotlin/com/swm/idle/application/applys/vo/CarerApplyNotificationInfo.kt @@ -0,0 +1,41 @@ +package com.swm.idle.application.applys.vo + +import com.swm.idle.domain.notification.enums.NotificationType +import com.swm.idle.domain.notification.jpa.NotificationInfo +import java.util.* + +data class CarerApplyNotificationInfo( + override val title: String, + override val body: String, + override val receiverId: UUID, + override val notificationType: NotificationType, + override val imageUrl: String?, + override val notificationDetails: Map?, +) : NotificationInfo { + + companion object { + + fun create( + title: String, + body: String, + receiverId: UUID, + notificationType: NotificationType, + imageUrl: String?, + jobPostingId: UUID, + ): CarerApplyNotificationInfo { + val notificationDetails = mapOf( + "jobPostingId" to jobPostingId, + ) + return CarerApplyNotificationInfo( + title, + body, + receiverId, + notificationType, + imageUrl, + notificationDetails, + ) + } + + } + +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt index 33800ef7..4ae18231 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/applys/event/ApplyEvent.kt @@ -1,23 +1,23 @@ package com.swm.idle.domain.applys.event -import com.swm.idle.domain.jobposting.entity.jpa.JobPosting import com.swm.idle.domain.notification.jpa.DeviceToken -import com.swm.idle.domain.user.carer.entity.jpa.Carer +import com.swm.idle.domain.notification.jpa.NotificationInfo +import java.util.* data class ApplyEvent( - val deviceTokens: List, - val jobPosting: JobPosting, - val carer: Carer, + val deviceToken: DeviceToken, + val notificationId: UUID, + val notificationInfo: NotificationInfo, ) { companion object { fun createApplyEvent( - deviceTokens: List, - jobPosting: JobPosting, - carer: Carer, + deviceToken: DeviceToken, + notificationId: UUID, + notificationInfo: NotificationInfo, ): ApplyEvent { - return ApplyEvent(deviceTokens, jobPosting, carer) + return ApplyEvent(deviceToken, notificationId, notificationInfo) } } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt index 567db68f..75220452 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/enums/NotificationType.kt @@ -1,5 +1,5 @@ package com.swm.idle.domain.notification.enums enum class NotificationType { - APPLICANT + APPLICANT, } diff --git a/idle-domain/src/main/resources/application-domain.yml b/idle-domain/src/main/resources/application-domain.yml index 73b540fd..285b72cb 100644 --- a/idle-domain/src/main/resources/application-domain.yml +++ b/idle-domain/src/main/resources/application-domain.yml @@ -32,5 +32,5 @@ spring: on-profile: dev jpa: hibernate: - ddl-auto: validate + ddl-auto: update show-sql: false diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt index 4ee5a9ec..fbaf7fa4 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/listener/CarerApplyEventListener.kt @@ -12,7 +12,7 @@ class CarerApplyEventListener( @EventListener fun handleApplyEvent(applyEvent: ApplyEvent) { - carerApplyEventService.sendForMulticast(applyEvent) + carerApplyEventService.send(applyEvent) } } diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt index 4fe41ff2..bc50d82a 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/applys/service/CarerApplyEventService.kt @@ -1,11 +1,10 @@ package com.swm.idle.infrastructure.fcm.applys.service -import com.google.firebase.messaging.MulticastMessage +import com.google.firebase.messaging.Message import com.google.firebase.messaging.Notification import com.swm.idle.domain.applys.event.ApplyEvent -import com.swm.idle.domain.user.common.vo.BirthYear import com.swm.idle.infrastructure.fcm.common.client.FcmClient -import com.swm.idle.infrastructure.fcm.common.enums.DestinationType +import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.stereotype.Component @Component @@ -13,43 +12,37 @@ class CarerApplyEventService( private val fcmClient: FcmClient, ) { + private val logger = KotlinLogging.logger {} - fun sendForMulticast(applyEvent: ApplyEvent) { - createMulticastMessage(applyEvent).also { - fcmClient.sendMulticast(it) + fun send(applyEvent: ApplyEvent) { + val message = createMessage(applyEvent) + + try { + fcmClient.send(message) + } catch (e: Exception) { + logger.warn { "FCM 알림 전송에 실패했습니다 : ${message}" } } } private fun createApplyNotification(applyEvent: ApplyEvent): Notification { return Notification.builder() - .setTitle("${applyEvent.carer.name} 님이 공고에 지원하였습니다.") - .setBody(createBodyMessage(applyEvent)) + .setTitle(applyEvent.notificationInfo.title) + .setBody(applyEvent.notificationInfo.body) .build() } - private fun createBodyMessage(applyEvent: ApplyEvent): String { - val filteredLotNumberAddress = applyEvent.jobPosting.lotNumberAddress.split(" ") - .take(3) - .joinToString(" ") - - return "$filteredLotNumberAddress " + - "${applyEvent.jobPosting.careLevel}등급 " + - "${BirthYear.calculateAge(applyEvent.jobPosting.birthYear)}세 " + - applyEvent.jobPosting.gender.value - } - - private fun createMulticastMessage(applyEvent: ApplyEvent): MulticastMessage { + private fun createMessage(applyEvent: ApplyEvent): Message { val applyNotification = createApplyNotification(applyEvent) - val deviceTokens = applyEvent.deviceTokens.map { deviceToken -> - deviceToken.deviceToken - } - - return MulticastMessage.builder() - .addAllTokens(deviceTokens) + return Message.builder() + .setToken(applyEvent.deviceToken.deviceToken) .setNotification(applyNotification) - .putData("destination", DestinationType.APPLICANTS.toString()) - .putData("jobPostingId", applyEvent.jobPosting.id.toString()) + .putData("notificationId", applyEvent.notificationId.toString()) + .putData("notificationType", applyEvent.notificationInfo.notificationType.toString()) + .putData( + "jobPostingId", + applyEvent.notificationInfo.notificationDetails!!["jobPostingId"].toString() + ) .build(); } diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt index 4f86eb17..4f776237 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/client/FcmClient.kt @@ -1,14 +1,14 @@ package com.swm.idle.infrastructure.fcm.common.client import com.google.firebase.messaging.FirebaseMessaging -import com.google.firebase.messaging.MulticastMessage +import com.google.firebase.messaging.Message import org.springframework.stereotype.Component @Component class FcmClient { - fun sendMulticast(message: MulticastMessage) { - FirebaseMessaging.getInstance().sendEachForMulticast(message) + fun send(message: Message) { + FirebaseMessaging.getInstance().sendAsync(message) } } diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml index 062a031e..a8cc7360 100644 --- a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml @@ -1,3 +1,3 @@ firebase: json: - path: ./firebase/swm-3idiots-firebase-adminsdk-si1at-8130a3deda.json + path: ./firebase/adminsdk.json From 18446fab12ee01c6f495d9a37127e97e06441398 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Sun, 20 Oct 2024 00:58:39 +0900 Subject: [PATCH 059/108] =?UTF-8?q?[IDLE-000]=20ci=20triggering=20branch?= =?UTF-8?q?=20=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-integrator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-integrator.yaml b/.github/workflows/dev-server-integrator.yaml index c43e997f..0cf1cc65 100644 --- a/.github/workflows/dev-server-integrator.yaml +++ b/.github/workflows/dev-server-integrator.yaml @@ -3,7 +3,7 @@ name: Develop Server Integrator (CI) on: push: branches: - - feat/IDLE-400 + - develop jobs: build_and_push: From 4cd29dcf2ee6be19ba7a28f83bcc920d15167917 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Sun, 20 Oct 2024 01:07:38 +0900 Subject: [PATCH 060/108] =?UTF-8?q?[IDLE-000]=20develop=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EC=97=90=EC=84=9C=20fcm=20service=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=ED=8C=8C=EC=9D=BC=20path=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-deployer.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-deployer.yaml b/.github/workflows/dev-server-deployer.yaml index 9f7febf2..46dc677e 100644 --- a/.github/workflows/dev-server-deployer.yaml +++ b/.github/workflows/dev-server-deployer.yaml @@ -46,7 +46,7 @@ jobs: - name: Set Up Firebase Service Key run: | mkdir ./idle-infrastructure/fcm/src/main/resources/firebase - echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > /idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json + echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > ./idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json - name: Copy Docker Compose file to server uses: appleboy/scp-action@master From 7f6ec0e6d07978d7e9d06238ab9fe92ade75cc44 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Sun, 20 Oct 2024 01:24:27 +0900 Subject: [PATCH 061/108] =?UTF-8?q?[IDLE-000]=20fcm=20service=20json=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idle-infrastructure/fcm/src/main/resources/application-fcm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml index a8cc7360..e448e5be 100644 --- a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml @@ -1,3 +1,3 @@ firebase: json: - path: ./firebase/adminsdk.json + path: ./firebase/adminkey.json From aae6944aa9db954a6e39237d820ab0dd51e5f8de Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 13:00:22 +0900 Subject: [PATCH 062/108] =?UTF-8?q?[IDLE-000]=20firebase=20service=20key?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EA=B2=BD=EB=A1=9C=20=EC=B2=B4=ED=81=AC?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=B4,=20cd=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8=EB=A5=BC=20=EC=88=98=EC=A0=95=ED=95=A9?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-deployer.yaml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-deployer.yaml b/.github/workflows/dev-server-deployer.yaml index 46dc677e..bcf3d5fa 100644 --- a/.github/workflows/dev-server-deployer.yaml +++ b/.github/workflows/dev-server-deployer.yaml @@ -45,9 +45,23 @@ jobs: - name: Set Up Firebase Service Key run: | - mkdir ./idle-infrastructure/fcm/src/main/resources/firebase + mkdir -p ./idle-infrastructure/fcm/src/main/resources/firebase echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > ./idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json + # 파일이 제대로 생성되었는지 확인 + if [ -f "./idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json" ]; then + echo "Firebase admin key file created successfully." + else + echo "Firebase admin key file not found. Listing directory contents..." + # 해당 디렉토리 구조 출력 + find ./idle-infrastructure/fcm/src/main/resources/firebase + fi + + # 상위 디렉토리까지 파일 구조 확인 + echo "Listing contents of ./idle-infrastructure/fcm/src/main/resources directory:" + find ./idle-infrastructure/fcm/src/main/resources + + - name: Copy Docker Compose file to server uses: appleboy/scp-action@master with: From 3a0bc7be39b4b2f68e69907da475f530885315df Mon Sep 17 00:00:00 2001 From: Wonjun You <59856002+wonjunYou@users.noreply.github.com> Date: Mon, 21 Oct 2024 13:06:09 +0900 Subject: [PATCH 063/108] Update README.md --- README.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ec8e0432..206d0797 100644 --- a/README.md +++ b/README.md @@ -21,15 +21,26 @@ - 이러한 문제를 해결하기 위해 시설이 고객의 요구에 맞는 요양 보호사를 빠르게 찾을 수 있도록 하여 구인 업무 부담을 줄이고, 요양 보호사는 조건에 맞는 공고를 쉽게 탐색하고 구직 제안을 받아 간편하게 일자리를 찾을 수 있도록 “케어밋” 을 기획.

-## 🌟 주요기능 +## 🌟 주요기능 +센터 관리자 측 +- 구인 공고 등록 및 관리 +- 구인 공고 등록 위치 기반 주변 요양 보호사 일괄 탐색 +- 요양 보호사 대상 구직 제안 +- 지원자 관리 기능 +- 프로필 관리 +- 신뢰도 높은 센터 가입 인증 절차 + +요양 보호사 +- 위치 기반 구인 공고 조회 및 필터링 기능 +- 설정한 필터에 부합하는 공고 등록 시, 알림 기능 +- 공고 지원 기능 +- 프로필 관리 - 구인 공고 등록 및 조회 -- 요양 보호사 주변 공고 등록 시 알림 기능 - 공고 즐겨찾기 기능 -- 공고 지원 및 채용 프로세스 -- 고객 주변 구직 중인 요양 보호사 일괄 탐색 -- 원하는 요양 보호사에 대한 구직 제안 -- 전화(안심번호 사용) + +공통 기능 - 채팅 +

## 🍎 참여자 From 4af0b50c299ef551f8ca1121dcf0cdb2466b39d9 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 13:36:06 +0900 Subject: [PATCH 064/108] =?UTF-8?q?[IDLE-000]=20fcm=20service=20key=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=EB=A5=BC=20class=20path=20=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95=20=EC=8B=9C=EB=8F=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idle-infrastructure/fcm/src/main/resources/application-fcm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml index e448e5be..d5fc0582 100644 --- a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml @@ -1,3 +1,3 @@ firebase: json: - path: ./firebase/adminkey.json + path: classpath:firebase/adminkey.json From 519558388e8e01fb1b39b29bb8a3ea2471fec3a7 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 13:37:50 +0900 Subject: [PATCH 065/108] =?UTF-8?q?[IDLE-000]=20ci=20triggering=20branch?= =?UTF-8?q?=20=EC=9E=84=EC=8B=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-integrator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-integrator.yaml b/.github/workflows/dev-server-integrator.yaml index 0cf1cc65..bd19d3a3 100644 --- a/.github/workflows/dev-server-integrator.yaml +++ b/.github/workflows/dev-server-integrator.yaml @@ -3,7 +3,7 @@ name: Develop Server Integrator (CI) on: push: branches: - - develop + - chore/IDLE-000 jobs: build_and_push: From a35c304a9e83a8a58846971263628c6a871894c1 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 13:48:06 +0900 Subject: [PATCH 066/108] =?UTF-8?q?[IDLE-000]=20firebaseApp=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20=EC=9E=84=EC=8B=9C=20=EB=B9=84=ED=99=9C?= =?UTF-8?q?=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index 739000f6..31863334 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -3,7 +3,6 @@ package com.swm.idle.infrastructure.fcm.common.config import com.google.auth.oauth2.GoogleCredentials import com.google.firebase.FirebaseApp import com.google.firebase.FirebaseOptions -import jakarta.annotation.PostConstruct import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Configuration import org.springframework.core.io.ClassPathResource @@ -14,7 +13,6 @@ class FirebaseConfig( var firebaseConfigJsonPath: String, ) { - @PostConstruct fun initializeFirebaseApp() { val googleCredentials = GoogleCredentials.fromStream(ClassPathResource(firebaseConfigJsonPath).inputStream) From 6588a7d9565c48206fe1f8104f583bcb34565ed8 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 13:58:13 +0900 Subject: [PATCH 067/108] =?UTF-8?q?[IDLE-000]=20firebaseApp=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20=EC=9E=84=EC=8B=9C=20=EB=B9=84=ED=99=9C?= =?UTF-8?q?=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fcm/common/config/FirebaseConfig.kt | 54 +++++++++---------- .../src/main/resources/application-fcm.yml | 6 +-- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index 31863334..3733a55e 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -1,27 +1,27 @@ -package com.swm.idle.infrastructure.fcm.common.config - -import com.google.auth.oauth2.GoogleCredentials -import com.google.firebase.FirebaseApp -import com.google.firebase.FirebaseOptions -import org.springframework.beans.factory.annotation.Value -import org.springframework.context.annotation.Configuration -import org.springframework.core.io.ClassPathResource - -@Configuration -class FirebaseConfig( - @Value("\${firebase.json.path}") - var firebaseConfigJsonPath: String, -) { - - fun initializeFirebaseApp() { - val googleCredentials = - GoogleCredentials.fromStream(ClassPathResource(firebaseConfigJsonPath).inputStream) - - val fireBaseOptions = FirebaseOptions.builder() - .setCredentials(googleCredentials) - .build() - - FirebaseApp.initializeApp(fireBaseOptions) - } - -} +//package com.swm.idle.infrastructure.fcm.common.config +// +//import com.google.auth.oauth2.GoogleCredentials +//import com.google.firebase.FirebaseApp +//import com.google.firebase.FirebaseOptions +//import org.springframework.beans.factory.annotation.Value +//import org.springframework.context.annotation.Configuration +//import org.springframework.core.io.ClassPathResource +// +//@Configuration +//class FirebaseConfig( +// @Value("\${firebase.json.path}") +// var firebaseConfigJsonPath: String, +//) { +// +// fun initializeFirebaseApp() { +// val googleCredentials = +// GoogleCredentials.fromStream(ClassPathResource(firebaseConfigJsonPath).inputStream) +// +// val fireBaseOptions = FirebaseOptions.builder() +// .setCredentials(googleCredentials) +// .build() +// +// FirebaseApp.initializeApp(fireBaseOptions) +// } +// +//} diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml index d5fc0582..4db02831 100644 --- a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml @@ -1,3 +1,3 @@ -firebase: - json: - path: classpath:firebase/adminkey.json +#firebase: +# json: +# path: classpath:firebase/adminkey.json From 463ed79eee62665f715c3b42a62fed2cbb9b4a3d Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 14:15:20 +0900 Subject: [PATCH 068/108] =?UTF-8?q?[IDLE-000]=20firebaseApp=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20=EC=9E=84=EC=8B=9C=20=EB=B9=84=ED=99=9C?= =?UTF-8?q?=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fcm/common/config/FirebaseConfig.kt | 27 ------------------- .../src/main/resources/application-fcm.yml | 3 --- 2 files changed, 30 deletions(-) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index 3733a55e..e69de29b 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -1,27 +0,0 @@ -//package com.swm.idle.infrastructure.fcm.common.config -// -//import com.google.auth.oauth2.GoogleCredentials -//import com.google.firebase.FirebaseApp -//import com.google.firebase.FirebaseOptions -//import org.springframework.beans.factory.annotation.Value -//import org.springframework.context.annotation.Configuration -//import org.springframework.core.io.ClassPathResource -// -//@Configuration -//class FirebaseConfig( -// @Value("\${firebase.json.path}") -// var firebaseConfigJsonPath: String, -//) { -// -// fun initializeFirebaseApp() { -// val googleCredentials = -// GoogleCredentials.fromStream(ClassPathResource(firebaseConfigJsonPath).inputStream) -// -// val fireBaseOptions = FirebaseOptions.builder() -// .setCredentials(googleCredentials) -// .build() -// -// FirebaseApp.initializeApp(fireBaseOptions) -// } -// -//} diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml index 4db02831..e69de29b 100644 --- a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml @@ -1,3 +0,0 @@ -#firebase: -# json: -# path: classpath:firebase/adminkey.json From 29be244264903da7bfa090561be1ea874304a18d Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 15:02:08 +0900 Subject: [PATCH 069/108] =?UTF-8?q?[IDLE-000]=20file=20path=20=EC=95=9E?= =?UTF-8?q?=EC=97=90=20./=20=EC=A0=9C=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fcm/common/config/FirebaseConfig.kt | 29 +++++++++++++++++++ .../src/main/resources/application-fcm.yml | 3 ++ 2 files changed, 32 insertions(+) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index e69de29b..739000f6 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -0,0 +1,29 @@ +package com.swm.idle.infrastructure.fcm.common.config + +import com.google.auth.oauth2.GoogleCredentials +import com.google.firebase.FirebaseApp +import com.google.firebase.FirebaseOptions +import jakarta.annotation.PostConstruct +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Configuration +import org.springframework.core.io.ClassPathResource + +@Configuration +class FirebaseConfig( + @Value("\${firebase.json.path}") + var firebaseConfigJsonPath: String, +) { + + @PostConstruct + fun initializeFirebaseApp() { + val googleCredentials = + GoogleCredentials.fromStream(ClassPathResource(firebaseConfigJsonPath).inputStream) + + val fireBaseOptions = FirebaseOptions.builder() + .setCredentials(googleCredentials) + .build() + + FirebaseApp.initializeApp(fireBaseOptions) + } + +} diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml index e69de29b..d529f85c 100644 --- a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml @@ -0,0 +1,3 @@ +firebase: + json: + path: firebase/adminkey.json From 504481dd6d552161e5b14e286a1626258dac0158 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 15:13:28 +0900 Subject: [PATCH 070/108] =?UTF-8?q?[IDLE-000]=20=EC=A0=88=EB=8C=80=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EC=8B=9C?= =?UTF-8?q?=EB=8F=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idle-infrastructure/fcm/src/main/resources/application-fcm.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml index d529f85c..0f8fb275 100644 --- a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml @@ -1,3 +1,3 @@ firebase: json: - path: firebase/adminkey.json + path: ./idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json From e06a453b690f74a8342627d80e7058d0c4074c54 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 15:30:08 +0900 Subject: [PATCH 071/108] =?UTF-8?q?[IDLE-000]=20fcm=20service=20key=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20path=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-deployer.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-deployer.yaml b/.github/workflows/dev-server-deployer.yaml index bcf3d5fa..b62426e7 100644 --- a/.github/workflows/dev-server-deployer.yaml +++ b/.github/workflows/dev-server-deployer.yaml @@ -45,7 +45,7 @@ jobs: - name: Set Up Firebase Service Key run: | - mkdir -p ./idle-infrastructure/fcm/src/main/resources/firebase + mkdir -p ./idle-infrastructure/fcm/src/main/resources/firebase/ echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > ./idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json # 파일이 제대로 생성되었는지 확인 From a4af5497847d928431d73a11eb7a58fe5080ebc2 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 16:00:56 +0900 Subject: [PATCH 072/108] =?UTF-8?q?[IDLE-000]=20fcm=20service=20key=20json?= =?UTF-8?q?=20file=20=EC=83=9D=EC=84=B1=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-deployer.yaml | 34 +++++++++++-------- .../src/main/resources/application-fcm.yml | 2 +- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/.github/workflows/dev-server-deployer.yaml b/.github/workflows/dev-server-deployer.yaml index b62426e7..8fd86e3f 100644 --- a/.github/workflows/dev-server-deployer.yaml +++ b/.github/workflows/dev-server-deployer.yaml @@ -43,24 +43,28 @@ jobs: --port 22 \ --cidr ${{ steps.publicip.outputs.ip }}/32 - - name: Set Up Firebase Service Key + - name: Create firebase directory run: | - mkdir -p ./idle-infrastructure/fcm/src/main/resources/firebase/ - echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > ./idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json + mkdir ./idle-infrastructure/fcm/src/main/resources/firebase/ - # 파일이 제대로 생성되었는지 확인 - if [ -f "./idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json" ]; then - echo "Firebase admin key file created successfully." - else - echo "Firebase admin key file not found. Listing directory contents..." - # 해당 디렉토리 구조 출력 - find ./idle-infrastructure/fcm/src/main/resources/firebase - fi + - name: Create Firebase Admin SDK JSON file + id: create-json + uses: jsdaniell/create-json@v1.2.3 + with: + name: "adminkey.json" + json: ${{ secrets.FIREBASE_SERVICE_KEY_FILE }} + dir: './idle-infrastructure/fcm/src/main/resources/firebase/' + + - name: Create firebase directory + run: mkdir ./client/src/main/resources/firebase/ - # 상위 디렉토리까지 파일 구조 확인 - echo "Listing contents of ./idle-infrastructure/fcm/src/main/resources directory:" - find ./idle-infrastructure/fcm/src/main/resources - + - name: Create Firebase Admin SDK JSON file + id: create-json + uses: jsdaniell/create-json@v1.2.3 + with: + name: "blooming-firebase-adminsdk.json" + json: ${{ secrets.FIREBASE_ADMIN_SDK_JSON }} + dir: './client/src/main/resources/firebase/' - name: Copy Docker Compose file to server uses: appleboy/scp-action@master diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml index 0f8fb275..51e699f2 100644 --- a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml @@ -1,3 +1,3 @@ firebase: json: - path: ./idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json + path: ./firebase/adminkey.json From 8e1502faa8554e12b76db9b0896bef86c66f79e8 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 16:01:51 +0900 Subject: [PATCH 073/108] =?UTF-8?q?[IDLE-000]=20ci=20triggering=20branch?= =?UTF-8?q?=20develop=EC=9C=BC=EB=A1=9C=20=EB=A1=A4=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-integrator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-integrator.yaml b/.github/workflows/dev-server-integrator.yaml index bd19d3a3..0cf1cc65 100644 --- a/.github/workflows/dev-server-integrator.yaml +++ b/.github/workflows/dev-server-integrator.yaml @@ -3,7 +3,7 @@ name: Develop Server Integrator (CI) on: push: branches: - - chore/IDLE-000 + - develop jobs: build_and_push: From d76a3a377744bac86274e6881f5a6ae488c5d906 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 16:15:22 +0900 Subject: [PATCH 074/108] =?UTF-8?q?[IDLE-000]=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-deployer.yaml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/workflows/dev-server-deployer.yaml b/.github/workflows/dev-server-deployer.yaml index 8fd86e3f..c6542d78 100644 --- a/.github/workflows/dev-server-deployer.yaml +++ b/.github/workflows/dev-server-deployer.yaml @@ -44,8 +44,7 @@ jobs: --cidr ${{ steps.publicip.outputs.ip }}/32 - name: Create firebase directory - run: | - mkdir ./idle-infrastructure/fcm/src/main/resources/firebase/ + run: mkdir ./idle-infrastructure/fcm/src/main/resources/firebase/ - name: Create Firebase Admin SDK JSON file id: create-json @@ -55,17 +54,6 @@ jobs: json: ${{ secrets.FIREBASE_SERVICE_KEY_FILE }} dir: './idle-infrastructure/fcm/src/main/resources/firebase/' - - name: Create firebase directory - run: mkdir ./client/src/main/resources/firebase/ - - - name: Create Firebase Admin SDK JSON file - id: create-json - uses: jsdaniell/create-json@v1.2.3 - with: - name: "blooming-firebase-adminsdk.json" - json: ${{ secrets.FIREBASE_ADMIN_SDK_JSON }} - dir: './client/src/main/resources/firebase/' - - name: Copy Docker Compose file to server uses: appleboy/scp-action@master with: From 724de910d474d03934d0c9b73dcb20f40b4fd55a Mon Sep 17 00:00:00 2001 From: Wonjun You <59856002+wonjunYou@users.noreply.github.com> Date: Mon, 21 Oct 2024 20:27:01 +0900 Subject: [PATCH 075/108] =?UTF-8?q?[IDLE-000]=20firebase=20config=EC=9D=98?= =?UTF-8?q?=20=ED=98=84=EC=9E=AC=20=EA=B2=BD=EB=A1=9C=EB=A5=BC=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=ED=95=98=EB=8F=84=EB=A1=9D=20print=EB=AC=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#197)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [IDLE-000] firebase config의 현재 경로를 출력하도록 print문 추가 * [IDLE-000] ci triggering branch 수정 * [IDLE-000] ci triggering branch 수정 * [IDLE-000] firebase app 초기화 로직 주석 처리 * [IDLE-000] firebase app 초기화 로직 주석 처리 * [IDLE-000] firebase app 초기화 로직 주석 처리 * [IDLE-000] file 대신 string으로 주입받아 초기화하는 방식으로 전환 * [IDLE-000] 일반 string 대신 base64 인코딩 된 문자열을 주입하도록 처리 * [IDLE-000] 일반 string 주입으로 rollback * [IDLE-000] json string log 추가 * [IDLE-000] base64 문자열로 재 변경 --- .github/workflows/dev-server-deployer.yaml | 11 ------- .github/workflows/dev-server-integrator.yaml | 2 +- .../fcm/common/config/FirebaseConfig.kt | 30 +++++++++++++------ .../src/main/resources/application-fcm.yml | 3 +- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/dev-server-deployer.yaml b/.github/workflows/dev-server-deployer.yaml index c6542d78..099528a2 100644 --- a/.github/workflows/dev-server-deployer.yaml +++ b/.github/workflows/dev-server-deployer.yaml @@ -43,17 +43,6 @@ jobs: --port 22 \ --cidr ${{ steps.publicip.outputs.ip }}/32 - - name: Create firebase directory - run: mkdir ./idle-infrastructure/fcm/src/main/resources/firebase/ - - - name: Create Firebase Admin SDK JSON file - id: create-json - uses: jsdaniell/create-json@v1.2.3 - with: - name: "adminkey.json" - json: ${{ secrets.FIREBASE_SERVICE_KEY_FILE }} - dir: './idle-infrastructure/fcm/src/main/resources/firebase/' - - name: Copy Docker Compose file to server uses: appleboy/scp-action@master with: diff --git a/.github/workflows/dev-server-integrator.yaml b/.github/workflows/dev-server-integrator.yaml index 0cf1cc65..b75dbc78 100644 --- a/.github/workflows/dev-server-integrator.yaml +++ b/.github/workflows/dev-server-integrator.yaml @@ -3,7 +3,7 @@ name: Develop Server Integrator (CI) on: push: branches: - - develop + - docs/IDLE-000 jobs: build_and_push: diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index 739000f6..7f452637 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -3,27 +3,39 @@ package com.swm.idle.infrastructure.fcm.common.config import com.google.auth.oauth2.GoogleCredentials import com.google.firebase.FirebaseApp import com.google.firebase.FirebaseOptions +import io.github.oshai.kotlinlogging.KotlinLogging import jakarta.annotation.PostConstruct import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Configuration -import org.springframework.core.io.ClassPathResource +import java.io.ByteArrayInputStream +import java.util.* @Configuration class FirebaseConfig( - @Value("\${firebase.json.path}") - var firebaseConfigJsonPath: String, + @Value("\${firebase.json}") + private val firebaseJsonBase64: String, ) { + private val logger = KotlinLogging.logger {} + @PostConstruct fun initializeFirebaseApp() { - val googleCredentials = - GoogleCredentials.fromStream(ClassPathResource(firebaseConfigJsonPath).inputStream) + try { + val decodedBytes = Base64.getDecoder().decode(firebaseJsonBase64) + val inputStream = ByteArrayInputStream(decodedBytes) + + val googleCredentials = GoogleCredentials.fromStream(inputStream) + + val fireBaseOptions = FirebaseOptions.builder() + .setCredentials(googleCredentials) + .build() - val fireBaseOptions = FirebaseOptions.builder() - .setCredentials(googleCredentials) - .build() + FirebaseApp.initializeApp(fireBaseOptions) - FirebaseApp.initializeApp(fireBaseOptions) + logger.info { "FirebaseApp has been initialized successfully." } + } catch (e: Exception) { + logger.error(e) { "Error initializing FirebaseApp." } + } } } diff --git a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml index 51e699f2..ca36b1db 100644 --- a/idle-infrastructure/fcm/src/main/resources/application-fcm.yml +++ b/idle-infrastructure/fcm/src/main/resources/application-fcm.yml @@ -1,3 +1,2 @@ firebase: - json: - path: ./firebase/adminkey.json + json: ${FIREBASE_SERVICE_KEY_JSON} From 78c58fa5af30afc7b38e3c4cbd22bc582674222d Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 16:51:54 +0900 Subject: [PATCH 076/108] =?UTF-8?q?[IDLE-000]=20firebase=20config=EC=9D=98?= =?UTF-8?q?=20=ED=98=84=EC=9E=AC=20=EA=B2=BD=EB=A1=9C=EB=A5=BC=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=ED=95=98=EB=8F=84=EB=A1=9D=20print=EB=AC=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../idle/infrastructure/fcm/common/config/FirebaseConfig.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index 7f452637..d65ee790 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -38,4 +38,10 @@ class FirebaseConfig( } } + @PostConstruct + fun printWorkingDirectory() { + println("Current working directory: " + System.getProperty("user.dir")) + } + + } From 89f7cf8d1bea98cd3080e658a83f1d163b13b399 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 22 Oct 2024 11:35:45 +0900 Subject: [PATCH 077/108] =?UTF-8?q?[IDLE-429]=20DB=20=ED=98=95=EC=83=81?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20Flyway=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/libs.versions.toml | 4 ++++ idle-domain/build.gradle.kts | 3 +++ idle-domain/src/main/resources/application-domain.yml | 10 ++++++++-- .../src/main/resources/db/migration/V1__init.sql | 0 4 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 idle-domain/src/main/resources/db/migration/V1__init.sql diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 98b66500..bee47496 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -44,6 +44,7 @@ jackson-module-kotlin = "2.17.0" sentry = "7.14.0" fcm = "9.3.0" +flyway = "10.2.0" [libraries] kotlin-reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" } @@ -105,6 +106,9 @@ sentry-logback = { group = "io.sentry", name = "sentry-logback", version.ref = " fcm = { group = 'com.google.firebase', name = 'firebase-admin', version.ref = "fcm"} +flyway-core = { group = 'org.flywaydb', name = 'flyway-core', version.ref = "flyway"} +flyway-mysql = { group = 'org.flywaydb', name = 'flyway-mysql', version.ref = "flyway"} + [plugins] sonarqube = { id = "org.sonarqube", version.ref = "sonar-cloud" } spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" } diff --git a/idle-domain/build.gradle.kts b/idle-domain/build.gradle.kts index 7d583c7d..bb008a64 100644 --- a/idle-domain/build.gradle.kts +++ b/idle-domain/build.gradle.kts @@ -14,6 +14,9 @@ dependencies { implementation(libs.spring.boot.starter.data.redis) implementation(libs.querydsl.spatial) implementation(libs.hibernate.spatial) + implementation(libs.flyway.core) + implementation(libs.flyway.mysql) runtimeOnly(libs.mysql.connector.java) + } diff --git a/idle-domain/src/main/resources/application-domain.yml b/idle-domain/src/main/resources/application-domain.yml index 285b72cb..9f8c6dc5 100644 --- a/idle-domain/src/main/resources/application-domain.yml +++ b/idle-domain/src/main/resources/application-domain.yml @@ -14,6 +14,12 @@ spring: host: ${REDIS_HOST:localhost} port: ${REDIS_PORT:6379} password: ${REDIS_PASSWORD:redis} + flyway: + enabled: true + baseline-on-migrate: true + locations: classpath:/db/migration + baseline-version: 0 + --- spring: config: @@ -21,7 +27,7 @@ spring: on-profile: local jpa: hibernate: - ddl-auto: update + ddl-auto: validate show-sql: true properties: hibernate.format_sql: true @@ -32,5 +38,5 @@ spring: on-profile: dev jpa: hibernate: - ddl-auto: update + ddl-auto: validate show-sql: false diff --git a/idle-domain/src/main/resources/db/migration/V1__init.sql b/idle-domain/src/main/resources/db/migration/V1__init.sql new file mode 100644 index 00000000..e69de29b From 2f9c5e6bc1531771b1f3949e6f6fd0d152706a1d Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 22 Oct 2024 11:44:18 +0900 Subject: [PATCH 078/108] =?UTF-8?q?[IDLE-429]=20Flyway=20latest=20version?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bee47496..3e38f7ef 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -44,7 +44,7 @@ jackson-module-kotlin = "2.17.0" sentry = "7.14.0" fcm = "9.3.0" -flyway = "10.2.0" +flyway = "10.20.0" [libraries] kotlin-reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" } From e9668d2767f7f93899bb08b4e076e15aa8c288cd Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 22 Oct 2024 11:44:45 +0900 Subject: [PATCH 079/108] =?UTF-8?q?[IDLE-429]=20=ED=94=BC=EB=93=9C?= =?UTF-8?q?=EB=B0=B1=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../idle/infrastructure/fcm/common/config/FirebaseConfig.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index d65ee790..7f452637 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -38,10 +38,4 @@ class FirebaseConfig( } } - @PostConstruct - fun printWorkingDirectory() { - println("Current working directory: " + System.getProperty("user.dir")) - } - - } From 7d45db85e692588e0b2f85d9f1410f07ccb4ef30 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 16:51:54 +0900 Subject: [PATCH 080/108] =?UTF-8?q?[IDLE-000]=20firebase=20config=EC=9D=98?= =?UTF-8?q?=20=ED=98=84=EC=9E=AC=20=EA=B2=BD=EB=A1=9C=EB=A5=BC=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=ED=95=98=EB=8F=84=EB=A1=9D=20print=EB=AC=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../idle/infrastructure/fcm/common/config/FirebaseConfig.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index 7f452637..d65ee790 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -38,4 +38,10 @@ class FirebaseConfig( } } + @PostConstruct + fun printWorkingDirectory() { + println("Current working directory: " + System.getProperty("user.dir")) + } + + } From b66513023af9ebe78fd0c75292f0cb300faf5057 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 22 Oct 2024 14:53:42 +0900 Subject: [PATCH 081/108] =?UTF-8?q?[IDLE-000]=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=B2=98=EB=A6=AC=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=EC=97=90=20@Transactional=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/notification/facade/NotificationFacadeService.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt index a4d7f648..0bd8783f 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/NotificationFacadeService.kt @@ -19,6 +19,7 @@ class NotificationFacadeService( private val notificationDetailsConverter: NotificationDetailsConverter, ) { + @Transactional fun readNotification(notificationId: UUID) { val notification = notificationService.getById(notificationId) From 8eeadbea30df4ad759140f6de74d55e63de1fb27 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 22 Oct 2024 14:55:44 +0900 Subject: [PATCH 082/108] =?UTF-8?q?[IDLE-000]=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=8B=9C,=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=81=20=EA=B8=B0=EC=A4=80=EC=9D=B4=20=EC=95=84?= =?UTF-8?q?=EB=8B=8C=20uuid=20v7=20id=20=EA=B8=B0=EC=A4=80=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=82=B4=EB=A6=BC=EC=B0=A8=EC=88=9C=20=EC=A0=95?= =?UTF-8?q?=EB=A0=AC=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/querydsl/NotificationQueryRepository.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt index 0b4dc2c2..c9bb7505 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt @@ -38,7 +38,7 @@ class NotificationQueryRepository( .and(next?.let { notification.id.goe(it) }) .and(notification.entityStatus.eq(EntityStatus.ACTIVE)) ) - .orderBy(notification.createdAt.desc()) + .orderBy(notification.id.desc()) .limit(limit) .fetch() } From 46adb7c8d3bcf7095c7c007420cd0e6e182bfd53 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 22 Oct 2024 15:01:05 +0900 Subject: [PATCH 083/108] =?UTF-8?q?[IDLE-000]=20CI=20=ED=8A=B8=EB=A6=AC?= =?UTF-8?q?=EA=B1=B0=20=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-integrator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-integrator.yaml b/.github/workflows/dev-server-integrator.yaml index b75dbc78..0cf1cc65 100644 --- a/.github/workflows/dev-server-integrator.yaml +++ b/.github/workflows/dev-server-integrator.yaml @@ -3,7 +3,7 @@ name: Develop Server Integrator (CI) on: push: branches: - - docs/IDLE-000 + - develop jobs: build_and_push: From bdcc55a1248bbeb256737577ffb3492fbfc75af7 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 22 Oct 2024 16:00:39 +0900 Subject: [PATCH 084/108] =?UTF-8?q?[IDLE-454]=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=A7=81=20=EC=88=98=ED=96=89=20=EC=8B=9C=EA=B0=81=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EB=B0=8F=20=EB=A1=9C=EA=B9=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/scheduler/CrawlingJobScheduler.kt | 2 +- .../com/swm/idle/batch/util/WorknetCrawler.kt | 16 +++++++++++++++- .../querydsl/NotificationQueryRepository.kt | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index ba7ba550..18153b57 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,7 +13,7 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 00 01 * * *") + @Scheduled(cron = "0 30 16 * * *") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt index d5c03414..0fba3768 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt @@ -51,7 +51,13 @@ object WorknetCrawler { } fun run(): List? { - initializeDriver() + try { + initializeDriver() + } catch (e: Exception) { + logger.error { e.toString() } + } + + logger.info { "=====초기화 완료, 크롤링 작업 시작" } val formatter = DateTimeFormatter.ofPattern("yyyyMMdd") val today = LocalDate.now().format(formatter) @@ -61,15 +67,23 @@ object WorknetCrawler { driver.get(crawlingUrl) + logger.info { "=====크롤링 url: $crawlingUrl" } + val wait = WebDriverWait(driver, Duration.ofSeconds(10)) wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"mForm\"]/div[2]/div/div[1]/div[1]/span/span"))) val jobPostingCountText = driver.findElement(By.xpath("//*[@id=\"mForm\"]/div[2]/div/div[1]/div[1]/span/span")).text + + logger.info { "=====크롤링 대상 공고 수: $jobPostingCountText" } + val jobPostingCount = Integer.parseInt(jobPostingCountText) + logger.info { "=====크롤링 페이지 수: $jobPostingCount" } + if (jobPostingCount == 0) { driver.quit() + logger.info { "=====크롤링 할 공고가 없어 미리 종료합니다." } return null } diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt index c9bb7505..d7cef434 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/querydsl/NotificationQueryRepository.kt @@ -35,7 +35,7 @@ class NotificationQueryRepository( .from(notification) .where( notification.receiverId.eq(userId) - .and(next?.let { notification.id.goe(it) }) + .and(next?.let { notification.id.loe(it) }) .and(notification.entityStatus.eq(EntityStatus.ACTIVE)) ) .orderBy(notification.id.desc()) From e339b0029325c784c22c7ad22ed414ff4ae4e348 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 15:15:11 +0900 Subject: [PATCH 085/108] =?UTF-8?q?[IDLE-000]=20=EA=B3=B5=EA=B3=A0=20?= =?UTF-8?q?=EB=B2=94=EC=9C=84=20=EA=B2=80=EC=83=89=20=EB=82=B4=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=B0=9C=EC=83=9D=20?= =?UTF-8?q?=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt | 2 +- .../repository/querydsl/JobPostingSpatialQueryRepository.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index 18153b57..dca9ec11 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,7 +13,7 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 30 16 * * *") + @Scheduled(cron = "0 00 16 * * *") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt index 7f824007..085f224c 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/jobposting/repository/querydsl/JobPostingSpatialQueryRepository.kt @@ -53,14 +53,14 @@ class JobPostingSpatialQueryRepository( jobPostingFavorite ) .from(jobPosting) - .innerJoin(jobPostingWeekday) + .leftJoin(jobPostingWeekday) .on(jobPosting.id.eq(jobPostingWeekday.jobPostingId)) .leftJoin(applys) .on( jobPosting.id.eq(applys.jobPostingId) .and(applys.carerId.eq(carer.id)) ) - .leftJoin(jobPostingFavorite).fetchJoin() + .leftJoin(jobPostingFavorite) .on(jobPosting.id.eq(jobPostingFavorite.jobPostingId)) .where(jobPosting.id.`in`(jobPostingIds)) .transform( From db5155950d242a96484bb2bfe2cc5953715afc81 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 15:15:42 +0900 Subject: [PATCH 086/108] =?UTF-8?q?[IDLE-000]=20ci=20=ED=8A=B8=EB=A6=AC?= =?UTF-8?q?=EA=B1=B0=20=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-integrator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-integrator.yaml b/.github/workflows/dev-server-integrator.yaml index 0cf1cc65..0b32f878 100644 --- a/.github/workflows/dev-server-integrator.yaml +++ b/.github/workflows/dev-server-integrator.yaml @@ -3,7 +3,7 @@ name: Develop Server Integrator (CI) on: push: branches: - - develop + - fix/IDLE-000 jobs: build_and_push: From cfa6e1af378eeb9bca05b0fc51267e43d2699270 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 15:28:44 +0900 Subject: [PATCH 087/108] =?UTF-8?q?[IDLE-000]=20ci=20=ED=8A=B8=EB=A6=AC?= =?UTF-8?q?=EA=B1=B0=20=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EB=A1=A4=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-server-integrator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-server-integrator.yaml b/.github/workflows/dev-server-integrator.yaml index 0b32f878..0cf1cc65 100644 --- a/.github/workflows/dev-server-integrator.yaml +++ b/.github/workflows/dev-server-integrator.yaml @@ -3,7 +3,7 @@ name: Develop Server Integrator (CI) on: push: branches: - - fix/IDLE-000 + - develop jobs: build_and_push: From da259c0899182fbd6772b4c60d8b5cbc03d81964 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 16:26:24 +0900 Subject: [PATCH 088/108] =?UTF-8?q?[IDLE-000]=20monitoring=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20actuator,=20promet?= =?UTF-8?q?heus=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-server-deployer.yaml | 7 +++++++ gradle/libs.versions.toml | 4 ++++ .../monitoring}/build.gradle.kts | 3 ++- settings.gradle.kts | 3 +++ 4 files changed, 16 insertions(+), 1 deletion(-) rename {idle-support/logging => idle-infrastructure/monitoring}/build.gradle.kts (66%) diff --git a/.github/workflows/prod-server-deployer.yaml b/.github/workflows/prod-server-deployer.yaml index 0bb2be04..b8cfb09f 100644 --- a/.github/workflows/prod-server-deployer.yaml +++ b/.github/workflows/prod-server-deployer.yaml @@ -57,6 +57,13 @@ jobs: else echo "Docker already installed." fi + if ! command -v docker-compose >/dev/null 2>&1; then + echo "Installing Docker Compose..." + sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + sudo chmod +x /usr/local/bin/docker-compose + else + echo "Docker Compose already installed." + fi - name: Configuration Env file uses: appleboy/ssh-action@master diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3e38f7ef..eaca796d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,6 +41,7 @@ jts-core = "1.19.0" jackson-module-kotlin = "2.17.0" +prometheus = "1.13.6" sentry = "7.14.0" fcm = "9.3.0" @@ -72,6 +73,7 @@ spring-mockk = { group = "com.ninja-squad", name = "springmockk", version.ref = kotest-runner-junit5 = { group = "io.kotest", name = "kotest-runner-junit5", version.ref = "kotest" } kotest-assertions-core = { group = "io.kotest", name = "kotest-assertions-core", version.ref = "kotest" } kotest-extensions-spring = { group = "io.kotest.extensions", name = "kotest-extensions-spring", version.ref = "kotest-extensions-spring" } +spring-boot-starter-actuator = { group = "org.spring.boot", name = "spring-boot-starter-actuator", version.ref = "spring-boot" } spring-boot-starter-test = { group = "org.springframework.boot", name = "spring-boot-starter-test", version.ref = "spring-boot" } kotest-extensions-testcontainers = { group = "io.kotest.extensions", name = "kotest-extensions-testcontainers", version.ref = "kotest-extensions-testcontainers" } testcontainers-junit-jupiter = { group = "org.testcontainers", name = "junit-jupiter", version.ref = "testcontainers" } @@ -109,6 +111,8 @@ fcm = { group = 'com.google.firebase', name = 'firebase-admin', version.ref = "f flyway-core = { group = 'org.flywaydb', name = 'flyway-core', version.ref = "flyway"} flyway-mysql = { group = 'org.flywaydb', name = 'flyway-mysql', version.ref = "flyway"} +prometheus = { group = "io.micrometer", name = "micrometer-registry-prometheus", version.ref = "prometheus" } + [plugins] sonarqube = { id = "org.sonarqube", version.ref = "sonar-cloud" } spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" } diff --git a/idle-support/logging/build.gradle.kts b/idle-infrastructure/monitoring/build.gradle.kts similarity index 66% rename from idle-support/logging/build.gradle.kts rename to idle-infrastructure/monitoring/build.gradle.kts index 121c6445..fe528b2b 100644 --- a/idle-support/logging/build.gradle.kts +++ b/idle-infrastructure/monitoring/build.gradle.kts @@ -7,5 +7,6 @@ bootJar.enabled = false jar.enabled = true dependencies { - + implementation(libs.prometheus) + implementation(libs.spring.boot.starter.actuator) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 37a887ae..d2f71582 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -25,6 +25,9 @@ project(":idle-infrastructure:sms").projectDir = file("idle-infrastructure/sms") include(":idle-infrastructure:fcm") project(":idle-infrastructure:fcm").projectDir = file("idle-infrastructure/fcm") +include(":idle-infrastructure:monitoring") +project(":idle-infrastructure:monitoring").projectDir = file("idle-infrastructure/monitoring") + // support modules include(":idle-support:common") project(":idle-support:common").projectDir = file("idle-support/common") From 62315c101b5ee5ec4fe36fe16a8c46a8f4df1348 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 16:32:16 +0900 Subject: [PATCH 089/108] =?UTF-8?q?[IDLE-456]=20monitoring.yml=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/application-monitoring.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 idle-infrastructure/monitoring/src/main/resources/application-monitoring.yml diff --git a/idle-infrastructure/monitoring/src/main/resources/application-monitoring.yml b/idle-infrastructure/monitoring/src/main/resources/application-monitoring.yml new file mode 100644 index 00000000..6bee27f7 --- /dev/null +++ b/idle-infrastructure/monitoring/src/main/resources/application-monitoring.yml @@ -0,0 +1,17 @@ +management: + endpoints: + health: + enabled: true + prometheus: + enabled: true + metrics: + enabled: true + web: + exposure: + include: health, prometheus, metrics + base-path: ${ACTUATOR_BASE_PATH} + jmx: + exposure: + exclude: "*" + server: + port: 9900 From 424b6217f9691f0539a8b76ba9b49c9323c92487 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 16:36:12 +0900 Subject: [PATCH 090/108] =?UTF-8?q?[IDLE-456]=20monitoring=20profile=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- idle-presentation/src/main/resources/application.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/idle-presentation/src/main/resources/application.yml b/idle-presentation/src/main/resources/application.yml index 2a9835cc..24f292d7 100644 --- a/idle-presentation/src/main/resources/application.yml +++ b/idle-presentation/src/main/resources/application.yml @@ -13,6 +13,7 @@ spring: - client - batch - fcm + - monitoring swagger: server: From 3dcb4c3f26e08b730a59b551c157e3e66e4b870d Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 16:40:40 +0900 Subject: [PATCH 091/108] =?UTF-8?q?[IDLE-456]=20actuator=20dependency=20gr?= =?UTF-8?q?oup=20name=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index eaca796d..80750d30 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -73,7 +73,7 @@ spring-mockk = { group = "com.ninja-squad", name = "springmockk", version.ref = kotest-runner-junit5 = { group = "io.kotest", name = "kotest-runner-junit5", version.ref = "kotest" } kotest-assertions-core = { group = "io.kotest", name = "kotest-assertions-core", version.ref = "kotest" } kotest-extensions-spring = { group = "io.kotest.extensions", name = "kotest-extensions-spring", version.ref = "kotest-extensions-spring" } -spring-boot-starter-actuator = { group = "org.spring.boot", name = "spring-boot-starter-actuator", version.ref = "spring-boot" } +spring-boot-starter-actuator = { group = "org.springframework.boot", name = "spring-boot-starter-actuator", version.ref = "spring-boot" } spring-boot-starter-test = { group = "org.springframework.boot", name = "spring-boot-starter-test", version.ref = "spring-boot" } kotest-extensions-testcontainers = { group = "io.kotest.extensions", name = "kotest-extensions-testcontainers", version.ref = "kotest-extensions-testcontainers" } testcontainers-junit-jupiter = { group = "org.testcontainers", name = "junit-jupiter", version.ref = "testcontainers" } From 94b8c36804551cecd2d987222e5a19b13b775217 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 17:00:26 +0900 Subject: [PATCH 092/108] =?UTF-8?q?[IDLE-000]=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=A7=81=20=EC=A3=BC=EA=B8=B0=20=ED=95=98=EB=A3=A8=202?= =?UTF-8?q?=ED=9A=8C=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index dca9ec11..417fe7f2 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,7 +13,7 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 00 16 * * *") + @Scheduled(cron = "0 0 1,13 * * *") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) From ba68cba81b15b5a0cfd433324b94d9acf8969891 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 17:00:38 +0900 Subject: [PATCH 093/108] =?UTF-8?q?[IDLE-000]=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=20=EB=A1=9C=EA=B7=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../idle/infrastructure/fcm/common/config/FirebaseConfig.kt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index d65ee790..7f452637 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -38,10 +38,4 @@ class FirebaseConfig( } } - @PostConstruct - fun printWorkingDirectory() { - println("Current working directory: " + System.getProperty("user.dir")) - } - - } From 2117f0a4a3508c14255dd7cb12e4b28b7919359c Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 17:01:03 +0900 Subject: [PATCH 094/108] =?UTF-8?q?[IDLE-000]=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20SMS=20=EB=82=B4=EC=9A=A9=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/swm/idle/infrastructure/sms/auth/service/SmsService.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/idle-infrastructure/sms/src/main/kotlin/com/swm/idle/infrastructure/sms/auth/service/SmsService.kt b/idle-infrastructure/sms/src/main/kotlin/com/swm/idle/infrastructure/sms/auth/service/SmsService.kt index 84442cc3..ab66cc23 100644 --- a/idle-infrastructure/sms/src/main/kotlin/com/swm/idle/infrastructure/sms/auth/service/SmsService.kt +++ b/idle-infrastructure/sms/src/main/kotlin/com/swm/idle/infrastructure/sms/auth/service/SmsService.kt @@ -40,9 +40,10 @@ class SmsService( } companion object { + const val MINIMUM_VERIFICATION_NUMBER = 100_000 const val VERIFICATION_NUMBER_SCALE = 900_000 - const val CENTER_VERIFICATION_MESSAGE_FORMAT = "[케어밋] 센터 회원가입 인증번호는 %s 입니다." + const val CENTER_VERIFICATION_MESSAGE_FORMAT = "[케어밋] 요청하신 인증번호는 %s 입니다." } } From 08bdc3108544a248cadbcaec0e9a30108ddf916e Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 23 Oct 2024 17:02:00 +0900 Subject: [PATCH 095/108] =?UTF-8?q?[IDLE-000]=20classPath=20=ED=95=98?= =?UTF-8?q?=EC=9C=84=20yaml=20=ED=8C=8C=EC=9D=BC=20=ED=99=95=EC=9E=A5?= =?UTF-8?q?=EC=9E=90=20=EB=AA=A8=EB=91=90=20.yml=EB=A1=9C=20=ED=86=B5?= =?UTF-8?q?=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/{application-aws.yaml => application-aws.yml} | 0 .../main/resources/{application-sms.yaml => application-sms.yml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename idle-infrastructure/aws/src/main/resources/{application-aws.yaml => application-aws.yml} (100%) rename idle-infrastructure/sms/src/main/resources/{application-sms.yaml => application-sms.yml} (100%) diff --git a/idle-infrastructure/aws/src/main/resources/application-aws.yaml b/idle-infrastructure/aws/src/main/resources/application-aws.yml similarity index 100% rename from idle-infrastructure/aws/src/main/resources/application-aws.yaml rename to idle-infrastructure/aws/src/main/resources/application-aws.yml diff --git a/idle-infrastructure/sms/src/main/resources/application-sms.yaml b/idle-infrastructure/sms/src/main/resources/application-sms.yml similarity index 100% rename from idle-infrastructure/sms/src/main/resources/application-sms.yaml rename to idle-infrastructure/sms/src/main/resources/application-sms.yml From 4f4a807fa3dc0f4f405b78780b441c0aa6a53c1d Mon Sep 17 00:00:00 2001 From: Wonjun You <59856002+wonjunYou@users.noreply.github.com> Date: Wed, 23 Oct 2024 18:01:10 +0900 Subject: [PATCH 096/108] =?UTF-8?q?[IDLE-000]=20=EC=A6=90=EA=B2=A8?= =?UTF-8?q?=EC=B0=BE=EA=B8=B0=20facade=20service=EC=97=90=20=ED=8A=B8?= =?UTF-8?q?=EB=9E=9C=EC=9E=AD=EC=85=98=20=EC=B6=94=EA=B0=80=20(#206)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [IDLE-000] firebase config의 현재 경로를 출력하도록 print문 추가 * [IDLE-000] facade service에 transaction 추가 --- .../jobposting/domain/JobPostingFavoriteService.kt | 6 +++--- .../jobposting/facade/JobPostingFavoriteFacadeService.kt | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingFavoriteService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingFavoriteService.kt index 729e9dff..305a3bee 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingFavoriteService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/domain/JobPostingFavoriteService.kt @@ -23,15 +23,15 @@ class JobPostingFavoriteService( val jobPostingFavorite = jobPostingFavoriteJpaRepository.findByJobPostingIdAndCarerId( jobPostingId = jobPostingId, carerId = carerId - ) ?: jobPostingFavoriteJpaRepository.save( + )?.let { + it.active() + } ?: jobPostingFavoriteJpaRepository.save( JobPostingFavorite( carerId = carerId, jobPostingId = jobPostingId, jobPostingType = jobPostingType, ) ) - - jobPostingFavorite.active() } @Transactional diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/JobPostingFavoriteFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/JobPostingFavoriteFacadeService.kt index 90daca5f..f7b2c640 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/JobPostingFavoriteFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/jobposting/facade/JobPostingFavoriteFacadeService.kt @@ -5,6 +5,7 @@ import com.swm.idle.application.jobposting.domain.JobPostingService import com.swm.idle.application.user.carer.domain.CarerService import com.swm.idle.domain.jobposting.enums.JobPostingType import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional import java.util.* @Service @@ -14,6 +15,7 @@ data class JobPostingFavoriteFacadeService( private val jobPostingService: JobPostingService, ) { + @Transactional fun createJobPostingFavorite( jobPostingId: UUID, carerId: UUID, @@ -31,6 +33,7 @@ data class JobPostingFavoriteFacadeService( ) } + @Transactional fun deleteJobPostingFavorite( jobPostingId: UUID, carerId: UUID, From 6a7107a5bc42cf9ad0cb6480026742ce51db79e7 Mon Sep 17 00:00:00 2001 From: Wonjun You <59856002+wonjunYou@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:28:56 +0900 Subject: [PATCH 097/108] =?UTF-8?q?[IDLE-461]=20=EC=9C=A0=EC=A0=80?= =?UTF-8?q?=EA=B0=80=20=EB=8B=A4=EC=A4=91=20=EB=94=94=EB=B0=94=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=EC=97=90=EC=84=9C=20=EC=95=8C=EB=A6=BC=EC=9D=84=20?= =?UTF-8?q?=EB=B0=9B=EC=9D=84=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0=ED=95=9C=EB=8B=A4.=20(#207)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [IDLE-000] firebase config의 현재 경로를 출력하도록 print문 추가 * [IDLE-461] 한 유저가 다중 디바이스 설정이 가능하도록 한다. --- .../application/applys/facade/CarerApplyFacadeService.kt | 8 +++++--- .../application/notification/domain/DeviceTokenService.kt | 4 ++-- .../repository/jpa/DeviceTokenJpaRepository.kt | 2 ++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt index 6af2e8ba..fc2b120a 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/applys/facade/CarerApplyFacadeService.kt @@ -59,10 +59,10 @@ class CarerApplyFacadeService( } } - centerManagers?.map { centerManager -> - val deviceToken = deviceTokenService.findByUserId(centerManager.id) + centerManagers?.forEach { centerManager -> + val deviceTokens = deviceTokenService.findAllByUserId(centerManager.id) - if (deviceToken != null) { + deviceTokens?.forEach { deviceToken -> val notificationInfo = CarerApplyNotificationInfo( title = "${carer.name} 님이 공고에 지원하였습니다.", body = createBodyMessage(jobPosting), @@ -85,6 +85,7 @@ class CarerApplyFacadeService( } } } + carerApplyService.create(jobPostingId, carer.id, applyMethodType) } @@ -98,4 +99,5 @@ class CarerApplyFacadeService( "${BirthYear.calculateAge(jobPosting.birthYear)}세 " + jobPosting.gender.value } + } diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt index f4674f3b..749b4ef7 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/domain/DeviceTokenService.kt @@ -17,8 +17,8 @@ class DeviceTokenService( return deviceTokenJpaRepository.findByDeviceToken(deviceToken) } - fun findByUserId(userId: UUID): DeviceToken? { - return deviceTokenJpaRepository.findByUserId(userId) + fun findAllByUserId(userId: UUID): List? { + return deviceTokenJpaRepository.findAllByUserId(userId) } @Transactional diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/jpa/DeviceTokenJpaRepository.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/jpa/DeviceTokenJpaRepository.kt index 7ecba361..f214e53d 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/jpa/DeviceTokenJpaRepository.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/notification/repository/jpa/DeviceTokenJpaRepository.kt @@ -14,4 +14,6 @@ interface DeviceTokenJpaRepository : JpaRepository { fun findByUserId(userId: UUID): DeviceToken? + fun findAllByUserId(userId: UUID): List? + } From 3a58baa953eaeb073dc9f6591a891dc5007ea080 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Mon, 21 Oct 2024 16:51:54 +0900 Subject: [PATCH 098/108] =?UTF-8?q?[IDLE-000]=20firebase=20config=EC=9D=98?= =?UTF-8?q?=20=ED=98=84=EC=9E=AC=20=EA=B2=BD=EB=A1=9C=EB=A5=BC=20=EC=B6=9C?= =?UTF-8?q?=EB=A0=A5=ED=95=98=EB=8F=84=EB=A1=9D=20print=EB=AC=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../idle/infrastructure/fcm/common/config/FirebaseConfig.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index 7f452637..d65ee790 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -38,4 +38,10 @@ class FirebaseConfig( } } + @PostConstruct + fun printWorkingDirectory() { + println("Current working directory: " + System.getProperty("user.dir")) + } + + } From 925d227ecb142a0fe724b0c342a2d8e65c9f55bb Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 25 Oct 2024 16:51:08 +0900 Subject: [PATCH 099/108] =?UTF-8?q?[IDLE-000]=20presentation=20module?= =?UTF-8?q?=EC=9D=98=20gradle=20=ED=8C=8C=EC=9D=BC=EC=97=90=20monitoring?= =?UTF-8?q?=20=EB=AA=A8=EB=93=88=20dependency=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../monitoring/src/main/resources/application-monitoring.yml | 1 + idle-presentation/build.gradle.kts | 1 + 2 files changed, 2 insertions(+) diff --git a/idle-infrastructure/monitoring/src/main/resources/application-monitoring.yml b/idle-infrastructure/monitoring/src/main/resources/application-monitoring.yml index 6bee27f7..042e7c40 100644 --- a/idle-infrastructure/monitoring/src/main/resources/application-monitoring.yml +++ b/idle-infrastructure/monitoring/src/main/resources/application-monitoring.yml @@ -6,6 +6,7 @@ management: enabled: true metrics: enabled: true + web: exposure: include: health, prometheus, metrics diff --git a/idle-presentation/build.gradle.kts b/idle-presentation/build.gradle.kts index db5162a8..24e97e3a 100644 --- a/idle-presentation/build.gradle.kts +++ b/idle-presentation/build.gradle.kts @@ -10,6 +10,7 @@ dependencies { implementation(project(":idle-infrastructure:client")) implementation(project(":idle-infrastructure:sms")) implementation(project(":idle-infrastructure:fcm")) + implementation(project(":idle-infrastructure:monitoring")) implementation(libs.spring.boot.starter.web) implementation(libs.spring.boot.starter.data.jpa) From e5cbbbcc64af853b461ff2122256ac2e2a8f647e Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 25 Oct 2024 16:51:37 +0900 Subject: [PATCH 100/108] =?UTF-8?q?[IDLE-000]=20deviceToken=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=EC=97=90=EC=84=9C=20=ED=8A=B8=EB=9E=9C?= =?UTF-8?q?=EC=9E=AD=EC=85=98=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notification/facade/DeviceTokenFacadeService.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/DeviceTokenFacadeService.kt b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/DeviceTokenFacadeService.kt index 3ffa1187..e7fe1c99 100644 --- a/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/DeviceTokenFacadeService.kt +++ b/idle-application/src/main/kotlin/com/swm/idle/application/notification/facade/DeviceTokenFacadeService.kt @@ -4,12 +4,15 @@ import com.swm.idle.application.common.security.getUserAuthentication import com.swm.idle.application.notification.domain.DeviceTokenService import com.swm.idle.domain.user.common.enum.UserType import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional @Service +@Transactional(readOnly = true) class DeviceTokenFacadeService( private val deviceTokenService: DeviceTokenService, ) { + @Transactional fun createDeviceToken(deviceToken: String, userType: UserType) { val userId = getUserAuthentication().userId deviceTokenService.findByDeviceToken(deviceToken)?.let { @@ -23,6 +26,7 @@ class DeviceTokenFacadeService( ) } + @Transactional fun deleteDeviceToken(deviceToken: String) { deviceTokenService.deleteByDeviceToken(deviceToken) } From e12205b5263489db175f58931a1d2784258959ac Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Fri, 25 Oct 2024 16:59:32 +0900 Subject: [PATCH 101/108] =?UTF-8?q?[IDLE-000]=20batch=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EC=9C=84=ED=95=B4=2030=EB=B6=84=EB=A7=88?= =?UTF-8?q?=EB=8B=A4=20=EB=8F=99=EC=9E=91=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index 417fe7f2..1a59deac 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,7 +13,7 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 0 1,13 * * *") + @Scheduled(cron = "0 0/30 * * * *") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) From d287b8312486c4fc7f1824bbc02a4fb284250ff2 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 29 Oct 2024 18:17:23 +0900 Subject: [PATCH 102/108] =?UTF-8?q?[IDLE-475]=20=EC=B1=84=ED=8C=85,=20?= =?UTF-8?q?=EC=B1=84=ED=8C=85=EB=B0=A9=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/chat/entity/jpa/ChatMessage.kt | 48 +++++++++++++++++++ .../idle/domain/chat/entity/jpa/ChatRoom.kt | 24 ++++++++++ .../swm/idle/domain/chat/enums/ContentType.kt | 5 ++ .../swm/idle/domain/chat/enums/SenderType.kt | 6 +++ .../com/swm/idle/domain/chat/vo/Content.kt | 8 ++++ .../com/swm/idle/domain/chat/vo/SendUser.kt | 7 +++ .../migration/V2__create_table_chat_room.sql | 13 +++++ .../V3__create_table_chat_message.sql | 19 ++++++++ 8 files changed, 130 insertions(+) create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/chat/entity/jpa/ChatMessage.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/chat/entity/jpa/ChatRoom.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/chat/enums/ContentType.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/chat/enums/SenderType.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/Content.kt create mode 100644 idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/SendUser.kt create mode 100644 idle-domain/src/main/resources/db/migration/V2__create_table_chat_room.sql create mode 100644 idle-domain/src/main/resources/db/migration/V3__create_table_chat_message.sql diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/entity/jpa/ChatMessage.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/entity/jpa/ChatMessage.kt new file mode 100644 index 00000000..e4d4ef35 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/entity/jpa/ChatMessage.kt @@ -0,0 +1,48 @@ +package com.swm.idle.domain.chat.entity.jpa + +import com.swm.idle.domain.chat.enums.ContentType +import com.swm.idle.domain.chat.enums.SenderType +//import com.swm.idle.domain.chat.vo.Content +import com.swm.idle.domain.common.entity.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.EnumType +import jakarta.persistence.Enumerated +import jakarta.persistence.Table +import org.hibernate.annotations.JdbcTypeCode +import org.hibernate.type.SqlTypes +import java.util.* + +@Entity +@Table(name = "chat_message") +class ChatMessage( + roomId: UUID, + senderId: UUID, + senderType: SenderType, + contents: List, +) : BaseEntity() { + + @Column(updatable = false) + var roomId: UUID = roomId + private set + + @Column(updatable = false) + var senderId: UUID = senderId + private set + + @Enumerated(EnumType.STRING) + @Column(name = "sender_type", updatable = false) + var senderType: SenderType = senderType + private set + + @JdbcTypeCode(SqlTypes.JSON) + @Column(name = "contents", nullable = false, columnDefinition = "json") + var contents: List = contents + private set + + data class Content( + val type: ContentType, + val value: String, + ) + +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/entity/jpa/ChatRoom.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/entity/jpa/ChatRoom.kt new file mode 100644 index 00000000..81aeca13 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/entity/jpa/ChatRoom.kt @@ -0,0 +1,24 @@ +package com.swm.idle.domain.chat.entity.jpa + +import com.swm.idle.domain.common.entity.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Table +import java.util.* + +@Entity +@Table(name = "chat_room") +class ChatRoom( + senderId: UUID, + receiverId: UUID, +) : BaseEntity() { + + @Column(nullable = false, updatable = false) + var senderId: UUID = senderId + private set + + @Column(nullable = false, updatable = false) + var receiverId: UUID = receiverId + private set + +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/enums/ContentType.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/enums/ContentType.kt new file mode 100644 index 00000000..24ee347c --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/enums/ContentType.kt @@ -0,0 +1,5 @@ +package com.swm.idle.domain.chat.enums + +enum class ContentType { + TEXT, +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/enums/SenderType.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/enums/SenderType.kt new file mode 100644 index 00000000..764a3822 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/enums/SenderType.kt @@ -0,0 +1,6 @@ +package com.swm.idle.domain.chat.enums + +enum class SenderType { + USER, + SYSTEM +} diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/Content.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/Content.kt new file mode 100644 index 00000000..382def16 --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/Content.kt @@ -0,0 +1,8 @@ +package com.swm.idle.domain.chat.vo + +import com.swm.idle.domain.chat.enums.ContentType + +data class Content( + val type: ContentType, + val value: String, +) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/SendUser.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/SendUser.kt new file mode 100644 index 00000000..5724593f --- /dev/null +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/SendUser.kt @@ -0,0 +1,7 @@ +package com.swm.idle.domain.chat.vo + +import java.util.* + +data class SendUser( + val userId: UUID, +) diff --git a/idle-domain/src/main/resources/db/migration/V2__create_table_chat_room.sql b/idle-domain/src/main/resources/db/migration/V2__create_table_chat_room.sql new file mode 100644 index 00000000..e3249c94 --- /dev/null +++ b/idle-domain/src/main/resources/db/migration/V2__create_table_chat_room.sql @@ -0,0 +1,13 @@ +-- V2__create_table_chat_room.sql + +-- Create table for chat room +CREATE TABLE chat_room ( + id BINARY(16) PRIMARY KEY, + sender_id BINARY(16) NOT NULL, + receiver_id BINARY(16) NOT NULL, + entity_status VARCHAR(50) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + INDEX (sender_id), + INDEX (receiver_id) +) diff --git a/idle-domain/src/main/resources/db/migration/V3__create_table_chat_message.sql b/idle-domain/src/main/resources/db/migration/V3__create_table_chat_message.sql new file mode 100644 index 00000000..434134a8 --- /dev/null +++ b/idle-domain/src/main/resources/db/migration/V3__create_table_chat_message.sql @@ -0,0 +1,19 @@ +-- V3__create_table_chat_message.sql + +-- Create table for chat message +CREATE TABLE chat_message ( + id BINARY(16) PRIMARY KEY, + room_id BINARY(16) NOT NULL, + sender_id BINARY(16) NOT NULL, + sender_type ENUM('USER', 'SYSTEM') NOT NULL, + contents JSON NOT NULL, + entity_status VARCHAR(50) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + INDEX (room_id), + INDEX (sender_id), + INDEX (created_at) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; + From 7e88e8d3b5e4009d47ab90d65373b7798a7423be Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Tue, 29 Oct 2024 18:48:21 +0900 Subject: [PATCH 103/108] =?UTF-8?q?[IDLE-475]=20=EC=B1=84=ED=8C=85=20?= =?UTF-8?q?=EB=A9=94=EC=84=B8=EC=A7=80=20=EC=B5=9C=EC=86=8C,=20=EC=B5=9C?= =?UTF-8?q?=EB=8C=80=20=EA=B8=B8=EC=9D=B4=20=EC=A0=9C=ED=95=9C=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/swm/idle/domain/chat/vo/Content.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/Content.kt b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/Content.kt index 382def16..96df7c89 100644 --- a/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/Content.kt +++ b/idle-domain/src/main/kotlin/com/swm/idle/domain/chat/vo/Content.kt @@ -5,4 +5,15 @@ import com.swm.idle.domain.chat.enums.ContentType data class Content( val type: ContentType, val value: String, -) +) { + + init { + require(value.isBlank()) { "채팅 메세지는 비어 있을 수 없습니다. " } + require(value.length <= MAXIMUM_CHAT_MESSAGE_LENGTH) { "채팅 메세지 최대 길이는 1,000자 입니다." } + } + + companion object { + + const val MAXIMUM_CHAT_MESSAGE_LENGTH = 1_000 + } +} From 25d8163e21ac12541aea2ce56d6fd0694cea72ff Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 30 Oct 2024 12:43:42 +0900 Subject: [PATCH 104/108] =?UTF-8?q?[IDLE-000]=20Batch=20=EB=A9=94=ED=83=80?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EB=B0=8F=20=ED=81=AC=EB=A1=A4=EB=A7=81=20=EC=88=98=ED=96=89=20?= =?UTF-8?q?=EC=A3=BC=EA=B8=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .../com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8182d514..dfa4be23 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ out/ ### JSON ### idle-infrastructure/fcm/src/main/resources/firebase +idle-batch/src/main/resources/script diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index 1a59deac..ba7ba550 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,7 +13,7 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 0/30 * * * *") + @Scheduled(cron = "0 00 01 * * *") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) From 0b58b69c7859ebaa2ea094fd216320f1cbc10cc6 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Wed, 30 Oct 2024 13:21:34 +0900 Subject: [PATCH 105/108] =?UTF-8?q?[IDLE-000]=20=EC=9A=B4=EC=98=81=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20CD=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20ste?= =?UTF-8?q?p=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-server-deployer.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/prod-server-deployer.yaml b/.github/workflows/prod-server-deployer.yaml index b8cfb09f..5f7bf6ed 100644 --- a/.github/workflows/prod-server-deployer.yaml +++ b/.github/workflows/prod-server-deployer.yaml @@ -80,11 +80,6 @@ jobs: jq -s '.[0] * .[1]' <(echo "$VARS_CONTEXT") <(echo "$SECRETS_CONTEXT") \ | jq -r 'to_entries | map("\(.key)=\(.value)") | .[]' > .env - - name: Set Up Firebase Service Key - run: | - mkdir ./idle-infrastructure/fcm/src/main/resources/firebase - echo ${{ secrets.FIREBASE_SERVICE_KEY_BASE64_ENCODE }} | base64 -d > ./idle-infrastructure/fcm/src/main/resources/firebase/adminkey.json - - name: Run Docker uses: appleboy/ssh-action@master with: From f283e6183c397d204d5079dc706cdaee720a4452 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Thu, 31 Oct 2024 13:24:38 +0900 Subject: [PATCH 106/108] =?UTF-8?q?[IDLE-000]=20=EB=8F=84=ED=85=90?= =?UTF-8?q?=EB=B8=8C=20=ED=8C=8C=EC=9D=BC=20=EA=B3=B5=EB=B0=B1=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1,=20=ED=81=AC=EB=A1=A4=EB=A7=81=20=EB=8C=80=EC=83=81?= =?UTF-8?q?=EC=9D=BC=EC=9E=90=20=EC=A0=84=EB=82=A0=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=EB=90=9C=20=EA=B3=B5=EA=B3=A0=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-server-deployer.yaml | 2 +- .../kotlin/com/swm/idle/batch/util/WorknetCrawler.kt | 10 +++++----- .../infrastructure/fcm/common/config/FirebaseConfig.kt | 6 ------ 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/.github/workflows/prod-server-deployer.yaml b/.github/workflows/prod-server-deployer.yaml index 5f7bf6ed..7338c213 100644 --- a/.github/workflows/prod-server-deployer.yaml +++ b/.github/workflows/prod-server-deployer.yaml @@ -78,7 +78,7 @@ jobs: script: | cd ~/app/docker jq -s '.[0] * .[1]' <(echo "$VARS_CONTEXT") <(echo "$SECRETS_CONTEXT") \ - | jq -r 'to_entries | map("\(.key)=\(.value)") | .[]' > .env + | jq -r 'to_entries | map("\(.key)=\(.value | gsub("[[:space:]]+$"; ""))") | .[]' > .env - name: Run Docker uses: appleboy/ssh-action@master diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt index 0fba3768..5dbccefe 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/util/WorknetCrawler.kt @@ -21,7 +21,7 @@ object WorknetCrawler { private val logger = KotlinLogging.logger { } private const val CRAWLING_TARGET_URL_FORMAT = - "https://www.work24.go.kr/wk/a/b/1200/retriveDtlEmpSrchList.do?basicSetupYn=&careerTo=&keywordJobCd=&occupation=&seqNo=&cloDateEndtParam=&payGbn=&templateInfo=&rot2WorkYn=&shsyWorkSecd=&srcKeywordParam=%EC%9A%94%EC%96%91%EB%B3%B4%ED%98%B8%EC%82%AC&resultCnt=10&keywordJobCont=&cert=&moreButtonYn=Y&minPay=&codeDepth2Info=11000¤tPageNo=1&eventNo=&mode=&major=&resrDutyExcYn=&eodwYn=&sortField=DATE&staArea=&sortOrderBy=DESC&keyword=%EC%9A%94%EC%96%91%EB%B3%B4%ED%98%B8%EC%82%AC&termSearchGbn=all&carrEssYns=&benefitSrchAndOr=O&disableEmpHopeGbn=&actServExcYn=&keywordStaAreaNm=&maxPay=&emailApplyYn=&codeDepth1Info=11000&keywordEtcYn=®DateStdtParam={today}&publDutyExcYn=&keywordJobCdSeqNo=&viewType=&exJobsCd=&templateDepthNmInfo=®ion=&employGbn=&empTpGbcd=&computerPreferential=&infaYn=&cloDateStdtParam=&siteClcd=WORK&searchMode=Y&birthFromYY=&indArea=&careerTypes=&subEmpHopeYn=&tlmgYn=&academicGbn=&templateDepthNoInfo=&foriegn=&entryRoute=&mealOfferClcd=&basicSetupYnChk=&station=&holidayGbn=&srcKeyword=%EC%9A%94%EC%96%91%EB%B3%B4%ED%98%B8%EC%82%AC&academicGbnoEdu=noEdu&enterPriseGbn=all&cloTermSearchGbn=all&birthToYY=&keywordWantedTitle=&stationNm=&benefitGbn=¬SrcKeywordParam=&keywordFlag=¬SrcKeyword=&essCertChk=&depth2SelCode=&keywordBusiNm=&preferentialGbn=&rot3WorkYn=®DateEndtParam={today}&pfMatterPreferential=&pageIndex={pageIndex}&termContractMmcnt=&careerFrom=&laborHrShortYn=#scrollLoc" + "https://www.work24.go.kr/wk/a/b/1200/retriveDtlEmpSrchList.do?basicSetupYn=&careerTo=&keywordJobCd=&occupation=&seqNo=&cloDateEndtParam=&payGbn=&templateInfo=&rot2WorkYn=&shsyWorkSecd=&srcKeywordParam=%EC%9A%94%EC%96%91%EB%B3%B4%ED%98%B8%EC%82%AC&resultCnt=10&keywordJobCont=&cert=&moreButtonYn=Y&minPay=&codeDepth2Info=11000¤tPageNo=1&eventNo=&mode=&major=&resrDutyExcYn=&eodwYn=&sortField=DATE&staArea=&sortOrderBy=DESC&keyword=%EC%9A%94%EC%96%91%EB%B3%B4%ED%98%B8%EC%82%AC&termSearchGbn=all&carrEssYns=&benefitSrchAndOr=O&disableEmpHopeGbn=&actServExcYn=&keywordStaAreaNm=&maxPay=&emailApplyYn=&codeDepth1Info=11000&keywordEtcYn=®DateStdtParam={yesterday}&publDutyExcYn=&keywordJobCdSeqNo=&viewType=&exJobsCd=&templateDepthNmInfo=®ion=&employGbn=&empTpGbcd=&computerPreferential=&infaYn=&cloDateStdtParam=&siteClcd=WORK&searchMode=Y&birthFromYY=&indArea=&careerTypes=&subEmpHopeYn=&tlmgYn=&academicGbn=&templateDepthNoInfo=&foriegn=&entryRoute=&mealOfferClcd=&basicSetupYnChk=&station=&holidayGbn=&srcKeyword=%EC%9A%94%EC%96%91%EB%B3%B4%ED%98%B8%EC%82%AC&academicGbnoEdu=noEdu&enterPriseGbn=all&cloTermSearchGbn=all&birthToYY=&keywordWantedTitle=&stationNm=&benefitGbn=¬SrcKeywordParam=&keywordFlag=¬SrcKeyword=&essCertChk=&depth2SelCode=&keywordBusiNm=&preferentialGbn=&rot3WorkYn=®DateEndtParam={yesterday}&pfMatterPreferential=&pageIndex={pageIndex}&termContractMmcnt=&careerFrom=&laborHrShortYn=#scrollLoc" private const val JOB_POSTING_COUNT_PER_PAGE = 50 @@ -60,9 +60,9 @@ object WorknetCrawler { logger.info { "=====초기화 완료, 크롤링 작업 시작" } val formatter = DateTimeFormatter.ofPattern("yyyyMMdd") - val today = LocalDate.now().format(formatter) + val yesterday = LocalDate.now().minusDays(1).format(formatter) val crawlingUrl = CRAWLING_TARGET_URL_FORMAT - .replace("{today}", today) + .replace("{yesterday}", yesterday) .replace("{pageIndex}", "1") driver.get(crawlingUrl) @@ -94,7 +94,7 @@ object WorknetCrawler { for (i in 1..pageCount) { if (i >= 2) { val updatedCrawlingUrl = crawlingUrl - .replace("{today}", today) + .replace("{yesterday}", yesterday) .replace(Regex("pageIndex=\\d+"), "pageIndex=${i}") driver.get(updatedCrawlingUrl) } @@ -108,7 +108,7 @@ object WorknetCrawler { if (lastPageJobPostingCount > 0) { val updateCrawlingUrl = crawlingUrl - .replace("{today}", today) + .replace("{yesterday}", yesterday) .replace(Regex("pageIndex=\\d+"), "pageIndex=${pageCount + 1}") driver.get(updateCrawlingUrl) diff --git a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt index d65ee790..7f452637 100644 --- a/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt +++ b/idle-infrastructure/fcm/src/main/kotlin/com/swm/idle/infrastructure/fcm/common/config/FirebaseConfig.kt @@ -38,10 +38,4 @@ class FirebaseConfig( } } - @PostConstruct - fun printWorkingDirectory() { - println("Current working directory: " + System.getProperty("user.dir")) - } - - } From b0a8d90e452e4d5ff8a056c3f1751b054364881f Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Thu, 31 Oct 2024 13:25:14 +0900 Subject: [PATCH 107/108] =?UTF-8?q?[IDLE-000]=20=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=EB=A7=81=20=EA=B8=B0=EC=A4=80=20=EC=8B=9C=EA=B0=81=2015?= =?UTF-8?q?=EC=8B=9C=EB=A1=9C=20=EC=9E=84=EC=8B=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt index ba7ba550..b289d35d 100644 --- a/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt +++ b/idle-batch/src/main/kotlin/com/swm/idle/batch/common/scheduler/CrawlingJobScheduler.kt @@ -13,7 +13,7 @@ class CrawlingJobScheduler( private val crawlingJobConfig: CrawlingJobConfig, ) { - @Scheduled(cron = "0 00 01 * * *") + @Scheduled(cron = "0 00 15 * * *") fun scheduleJob() { val jobParameters: JobParameters = JobParametersBuilder() .addLong("timestamp", System.currentTimeMillis()) From 25a4a39842af90d4154181c64d29afb2f99afdf2 Mon Sep 17 00:00:00 2001 From: wonjunYou Date: Thu, 31 Oct 2024 14:29:06 +0900 Subject: [PATCH 108/108] =?UTF-8?q?[IDLE-000]=20cd=20env=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=83=9D=EC=84=B1=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-server-deployer.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/prod-server-deployer.yaml b/.github/workflows/prod-server-deployer.yaml index 7338c213..cf998e6b 100644 --- a/.github/workflows/prod-server-deployer.yaml +++ b/.github/workflows/prod-server-deployer.yaml @@ -77,8 +77,8 @@ jobs: envs: VARS_CONTEXT,SECRETS_CONTEXT script: | cd ~/app/docker - jq -s '.[0] * .[1]' <(echo "$VARS_CONTEXT") <(echo "$SECRETS_CONTEXT") \ - | jq -r 'to_entries | map("\(.key)=\(.value | gsub("[[:space:]]+$"; ""))") | .[]' > .env + jq -s '.[0] * .[1] | del(.INSTANCE_PEM_KEY)' <(echo "$VARS_CONTEXT") <(echo "$SECRETS_CONTEXT") \ + | jq -r 'to_entries | map("\(.key)=\(.value)") | .[]' > .env - name: Run Docker uses: appleboy/ssh-action@master