From 17f302a1d53d4d5bcf5a83cab4b538f3e352c634 Mon Sep 17 00:00:00 2001 From: Amir Rajabi Date: Tue, 17 Feb 2026 18:35:38 +0330 Subject: [PATCH 1/7] Handle different modes of profile inquiries --- .../kotlin/co/nilin/opex/common/OpexError.kt | 3 +- docker-compose.yml | 2 ++ .../profile/app/service/ProfileManagement.kt | 31 ++++++++++++++----- .../src/main/resources/application.yml | 4 +-- .../dao/ProfileApprovalRequestRepository.kt | 2 +- .../ports/postgres/dao/ProfileRepository.kt | 3 ++ .../postgres/imp/ProfileManagementImp.kt | 7 ++++- ...p_profile_identifier_unique_constraint.sql | 2 ++ 8 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 profile/profile-ports/profile-postgres/src/main/resources/db/migration/V7__drop_profile_identifier_unique_constraint.sql diff --git a/common/src/main/kotlin/co/nilin/opex/common/OpexError.kt b/common/src/main/kotlin/co/nilin/opex/common/OpexError.kt index 8fab4bbe5..a93fffd30 100644 --- a/common/src/main/kotlin/co/nilin/opex/common/OpexError.kt +++ b/common/src/main/kotlin/co/nilin/opex/common/OpexError.kt @@ -197,7 +197,8 @@ enum class OpexError(val code: Int, val message: String?, val status: HttpStatus CardIbanInfoInquiryError(13045, "Card-IBAN info inquiry failed", HttpStatus.INTERNAL_SERVER_ERROR), BankAccountAlreadyExist(13046, "Bank account already exist", HttpStatus.BAD_REQUEST), BankAccountNotFound(13047, "Bank account not found", HttpStatus.NOT_FOUND), - AddressBookNotFound(13048, "Address book not found", HttpStatus.NOT_FOUND) + AddressBookNotFound(13048, "Address book not found", HttpStatus.NOT_FOUND), + InvalidProfileData(13049, "Invalid profile data", HttpStatus.BAD_REQUEST) ; override fun code() = this.code diff --git a/docker-compose.yml b/docker-compose.yml index fb352af93..28eb44c63 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -569,6 +569,8 @@ services: - ADMIN_APPROVAL_PROFILE_COMPLETION_REQUEST=${ADMIN_APPROVAL_PROFILE_COMPLETION_REQUEST} - ADMIN_APPROVAL_BANK_ACCOUNT=${ADMIN_APPROVAL_BANK_ACCOUNT} - TOKEN_ISSUER_URL=${KC_ISSUER_URL} + - MOBILE_IDENTITY_INQUIRY=${MOBILE_IDENTITY_INQUIRY} + - PERSONAL_IDENTITY_INQUIRY=${PERSONAL_IDENTITY_INQUIRY} depends_on: - kafka-1 - kafka-2 diff --git a/profile/profile-app/src/main/kotlin/co/nilin/opex/profile/app/service/ProfileManagement.kt b/profile/profile-app/src/main/kotlin/co/nilin/opex/profile/app/service/ProfileManagement.kt index a833018b3..74df80086 100644 --- a/profile/profile-app/src/main/kotlin/co/nilin/opex/profile/app/service/ProfileManagement.kt +++ b/profile/profile-app/src/main/kotlin/co/nilin/opex/profile/app/service/ProfileManagement.kt @@ -13,6 +13,7 @@ import co.nilin.opex.profile.core.data.profile.* import co.nilin.opex.profile.core.spi.* import co.nilin.opex.profile.core.utils.handleComparativeError import co.nilin.opex.profile.core.utils.handleShahkarError +import co.nilin.opex.utility.error.data.OpexException import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.reactive.awaitFirst import org.slf4j.LoggerFactory @@ -29,10 +30,10 @@ class ProfileManagement( private val otpProxy: OtpProxy, private val inquiryProxy: InquiryProxy, - @Value("\${app.inquiry.mobile-indentiy}") + @Value("\${app.inquiry.mobile-identity}") private var mobileIdentityEnabled: Boolean, - @Value("\${app.inquiry.personal-indentiy}") + @Value("\${app.inquiry.personal-identity}") private var personalIdentityEnabled: Boolean, @Value("\${app.admin-approval.profile-completion-request}") @@ -164,16 +165,32 @@ class ProfileManagement( ) ) - validateInquiryResponses(shahkarResponse, comparativeResponse) + try { + validateInquiryResponses(shahkarResponse, comparativeResponse) + } catch (e: OpexException) { + if (!isAdminApprovalRequired || + (e.error != OpexError.ShahkarInquiryError && e.error != OpexError.ComparativeInquiryError) + ) throw e + } + + val shahkarRequested = isIranian && mobileIdentityEnabled + val comparativeRequested = isIranian && personalIdentityEnabled - if (isIranian && !isAdminApprovalRequired) - return approveProfileAutomatically(userId, completedProfile) + val shahkarOk = !shahkarRequested || (shahkarResponse != null && !shahkarResponse.isError()) + val comparativeOk = !comparativeRequested || (comparativeResponse != null && !comparativeResponse.isError()) - return requestAdminApproval(userId) + val allRequestedInquiriesOk = shahkarOk && comparativeOk + val anyInquiryRequested = shahkarRequested || comparativeRequested + return when { + !isAdminApprovalRequired -> approveProfileAutomatically(userId, completedProfile) + isAdminApprovalRequired && !anyInquiryRequested -> requestAdminApproval(userId) + isAdminApprovalRequired && allRequestedInquiriesOk -> approveProfileAutomatically(userId, completedProfile) + else -> requestAdminApproval(userId) // At least one active inquiry has failed. + } } - private suspend fun approveProfileAutomatically(userId: String, completedProfile: Profile): Profile { + private suspend fun approveProfileAutomatically(userId: String, completedProfile: Profile): Profile { kycLevelUpdatedPublisher.publish( KycLevelUpdatedEvent(userId, KycLevel.LEVEL_2, LocalDateTime.now()) ) diff --git a/profile/profile-app/src/main/resources/application.yml b/profile/profile-app/src/main/resources/application.yml index cc91c40fb..f4b00c7ab 100644 --- a/profile/profile-app/src/main/resources/application.yml +++ b/profile/profile-app/src/main/resources/application.yml @@ -63,8 +63,8 @@ app: auth-gateway: url: lb://opex-auth-gateway inquiry: - mobile-indentiy: true - personal-indentiy: false + mobile-identity: ${MOBILE_IDENTITY_INQUIRY} + personal-identity: ${PERSONAL_IDENTITY_INQUIRY} url: ${JIBIT_URL} api-key: ${JIBIT_API_KEY} secret-key: ${JIBIT_SECRET_KEY} diff --git a/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/dao/ProfileApprovalRequestRepository.kt b/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/dao/ProfileApprovalRequestRepository.kt index 485305aa8..9b8486e8c 100644 --- a/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/dao/ProfileApprovalRequestRepository.kt +++ b/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/dao/ProfileApprovalRequestRepository.kt @@ -15,7 +15,7 @@ interface ProfileApprovalRequestRepository : ReactiveCrudRepository + ): Mono @Query( """ diff --git a/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/dao/ProfileRepository.kt b/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/dao/ProfileRepository.kt index e765ca535..45de9f700 100644 --- a/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/dao/ProfileRepository.kt +++ b/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/dao/ProfileRepository.kt @@ -17,6 +17,9 @@ interface ProfileRepository : ReactiveCrudRepository { fun findByUserId(userId: String): Mono + @Query("select * from profile where identifier = :identifier order by last_update_date desc limit 1") + fun findLatestByIdentifier(identifier: String ): Mono + @Query( """ SELECT * diff --git a/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/imp/ProfileManagementImp.kt b/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/imp/ProfileManagementImp.kt index 3c85109c0..d9c598a6c 100644 --- a/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/imp/ProfileManagementImp.kt +++ b/profile/profile-ports/profile-postgres/src/main/kotlin/co/nilin/opex/profile/ports/postgres/imp/ProfileManagementImp.kt @@ -19,7 +19,6 @@ import co.nilin.opex.profile.ports.postgres.model.entity.ProfileModel import co.nilin.opex.profile.ports.postgres.utils.RegexPatterns import co.nilin.opex.profile.ports.postgres.utils.toProfileModel import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.toList import kotlinx.coroutines.reactive.awaitFirstOrNull @@ -52,6 +51,12 @@ class ProfileManagementImp( val existingProfile = profileRepository.findByUserId(id)?.awaitFirstOrNull() ?: throw OpexError.ProfileNotfound.exception() + val latestProfileByIdentifier = profileRepository.findLatestByIdentifier(data.identifier).awaitFirstOrNull() + if (latestProfileByIdentifier != null && (latestProfileByIdentifier.status != + ProfileStatus.PROFILE_COMPLETED && latestProfileByIdentifier.status != + ProfileStatus.ADMIN_REJECTED) + ) throw OpexError.InvalidProfileData.exception() + val newProfileModel = data.toProfileModel( existing = existingProfile, mobileMatch = mobileIdentityMatch, diff --git a/profile/profile-ports/profile-postgres/src/main/resources/db/migration/V7__drop_profile_identifier_unique_constraint.sql b/profile/profile-ports/profile-postgres/src/main/resources/db/migration/V7__drop_profile_identifier_unique_constraint.sql new file mode 100644 index 000000000..5bfa0ebb8 --- /dev/null +++ b/profile/profile-ports/profile-postgres/src/main/resources/db/migration/V7__drop_profile_identifier_unique_constraint.sql @@ -0,0 +1,2 @@ +ALTER TABLE profile + DROP CONSTRAINT unique_identifier; \ No newline at end of file From 8a63d01d07b72abbd9da61900014ad364d3e918f Mon Sep 17 00:00:00 2001 From: Amir Rajabi Date: Wed, 18 Feb 2026 14:15:53 +0330 Subject: [PATCH 2/7] Update pr.yml --- .github/workflows/pr.yml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 04a1ab04d..44ff87f97 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -2,7 +2,7 @@ name: Build and test on pull request on: pull_request: - types: [ opened, synchronize, reopened ] + types: [ opened, synchronize, reopen ] jobs: build: @@ -14,18 +14,20 @@ jobs: steps: - name: Checkout Source Code uses: actions/checkout@v2 + - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: - distribution: 'adopt' - java-package: jdk + distribution: temurin java-version: ${{ matrix.java }} - # cache: maven - - name: Build - run: mvn -B clean install -Potc - - name: Run Tests - run: mvn -B -Dskip.unit.tests=false surefire:test + + - name: Verify Docker + run: docker info + + - name: Build and Test + run: mvn -B clean install -Potc + - name: Build Docker images env: TAG: pr - run: docker compose -f docker-compose.build.yml build + run: docker compose -f docker-compose.build.yml build \ No newline at end of file From 755789c527b2d50a1dafdb677a97e6175d168cf7 Mon Sep 17 00:00:00 2001 From: Amir Rajabi Date: Wed, 18 Feb 2026 16:34:05 +0330 Subject: [PATCH 3/7] Update pr.yml --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 44ff87f97..78d58cf2b 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -2,7 +2,7 @@ name: Build and test on pull request on: pull_request: - types: [ opened, synchronize, reopen ] + types: [ opened, synchronize, reopened ] jobs: build: From b218c59b5456a68deb1bc7da77d4e405a83b5dfd Mon Sep 17 00:00:00 2001 From: Amir Rajabi Date: Wed, 18 Feb 2026 16:41:35 +0330 Subject: [PATCH 4/7] update workflows --- .github/workflows/dev-otc.yml | 5 ++--- .github/workflows/dev.yml | 5 ++--- .github/workflows/main-otc.yml | 5 ++--- .github/workflows/main.yml | 5 ++--- .github/workflows/pr.yml | 17 +++++++---------- .github/workflows/test.yml | 5 ++--- 6 files changed, 17 insertions(+), 25 deletions(-) diff --git a/.github/workflows/dev-otc.yml b/.github/workflows/dev-otc.yml index 70e3993c9..22e22fff6 100644 --- a/.github/workflows/dev-otc.yml +++ b/.github/workflows/dev-otc.yml @@ -29,10 +29,9 @@ jobs: uses: actions/checkout@v2 - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: - distribution: 'adopt' - java-package: jdk + distribution: temurin java-version: ${{ matrix.java }} - name: Fetch partners config diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 9ca8609d7..a0409266b 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -16,10 +16,9 @@ jobs: - name: Checkout Source Code uses: actions/checkout@v2 - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: - distribution: 'adopt' - java-package: jdk + distribution: temurin java-version: ${{ matrix.java }} # cache: maven - name: Build diff --git a/.github/workflows/main-otc.yml b/.github/workflows/main-otc.yml index b515c0237..3710997fb 100644 --- a/.github/workflows/main-otc.yml +++ b/.github/workflows/main-otc.yml @@ -29,10 +29,9 @@ jobs: uses: actions/checkout@v2 - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: - distribution: 'adopt' - java-package: jdk + distribution: temurin java-version: ${{ matrix.java }} - name: Fetch partners config diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a72b0f314..82ec98ee7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,10 +16,9 @@ jobs: - name: Checkout Source Code uses: actions/checkout@v2 - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: - distribution: 'adopt' - java-package: jdk + distribution: temurin java-version: ${{ matrix.java }} # cache: maven - name: Build diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 78d58cf2b..7774014a7 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -14,19 +14,16 @@ jobs: steps: - name: Checkout Source Code uses: actions/checkout@v2 - - name: Setup Java uses: actions/setup-java@v4 with: - distribution: temurin - java-version: ${{ matrix.java }} - - - name: Verify Docker - run: docker info - - - name: Build and Test - run: mvn -B clean install -Potc - + distribution: temurin + java-version: ${{ matrix.java }} + # cache: maven + - name: Build + run: mvn -B clean install -Potc + - name: Run Tests + run: mvn -B -Dskip.unit.tests=false surefire:test - name: Build Docker images env: TAG: pr diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 28bb270ad..05f9a75c0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,10 +22,9 @@ jobs: - name: Checkout Source Code uses: actions/checkout@v2 - name: Setup Java - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: - distribution: 'adopt' - java-package: jdk + distribution: temurin java-version: ${{ matrix.java }} # cache: maven - name: Build From a3e1f4a0663ae2db4297d22ff8c2134b9694b38c Mon Sep 17 00:00:00 2001 From: Amir Rajabi Date: Wed, 18 Feb 2026 17:01:53 +0330 Subject: [PATCH 5/7] Update pr.yml --- .github/workflows/pr.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7774014a7..ce775d834 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -17,13 +17,11 @@ jobs: - name: Setup Java uses: actions/setup-java@v4 with: - distribution: temurin - java-version: ${{ matrix.java }} - # cache: maven - - name: Build - run: mvn -B clean install -Potc - - name: Run Tests - run: mvn -B -Dskip.unit.tests=false surefire:test + distribution: temurin + java-version: ${{ matrix.java }} + - name: Build and Test + run: mvn -B clean install -Potc + - name: Build Docker images env: TAG: pr From f809e8a33432236994e5f681884edbc460b9aca1 Mon Sep 17 00:00:00 2001 From: Amir Rajabi Date: Wed, 18 Feb 2026 17:29:16 +0330 Subject: [PATCH 6/7] Update pr.yml --- .github/workflows/pr.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index ce775d834..d668c00ac 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -21,7 +21,9 @@ jobs: java-version: ${{ matrix.java }} - name: Build and Test run: mvn -B clean install -Potc - + - name: Run Tests + run: mvn -B -Dskip.unit.tests=false surefire:test + - name: Build Docker images env: TAG: pr From 7d6ffe9d0887ed972e438c8b1262da2b92562427 Mon Sep 17 00:00:00 2001 From: Amir Rajabi Date: Wed, 18 Feb 2026 17:29:39 +0330 Subject: [PATCH 7/7] Update pr.yml --- .github/workflows/pr.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index d668c00ac..74af2bad1 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -19,11 +19,11 @@ jobs: with: distribution: temurin java-version: ${{ matrix.java }} - - name: Build and Test + - name: Build run: mvn -B clean install -Potc - name: Run Tests run: mvn -B -Dskip.unit.tests=false surefire:test - + - name: Build Docker images env: TAG: pr