This commit is contained in:
2026-08-05 09:11:26 +08:00
parent d544bbd0c5
commit 3791fee285
45 changed files with 1187 additions and 126 deletions
@@ -38,4 +38,28 @@ class QualificationUploadContractTest {
assertTrue(yaml.contains(" /api/merchant/v1/iam/tenant/qualifications/submit-review:"));
}
}
@Test
void internalControllerExposesBothRequiredPackageRoutes() {
var routes = java.util.Arrays.stream(InternalTenantController.class.getDeclaredMethods())
.map(method -> method.getAnnotation(PostMapping.class))
.filter(java.util.Objects::nonNull)
.flatMap(mapping -> java.util.Arrays.stream(mapping.value()))
.toList();
assertTrue(routes.contains("/required-qualification-packages"));
assertTrue(routes.contains("/platform-required-qualification-packages"));
}
@Test
void staticOpenApiDocumentsTheRequiredPackageContract() throws IOException {
try (var input = getClass().getClassLoader().getResourceAsStream("openapi/iam-v1.yaml")) {
assertNotNull(input);
String yaml = new String(input.readAllBytes(), StandardCharsets.UTF_8);
assertTrue(yaml.contains("/internal/iam/required-qualification-packages:"));
assertTrue(yaml.contains("/internal/iam/platform-required-qualification-packages:"));
assertTrue(yaml.contains("RequiredQualificationPackageRequest:"));
assertTrue(yaml.contains("replaceBusinessLicense"));
assertTrue(yaml.contains("replaceLegalPersonId"));
}
}
}
@@ -1,6 +1,7 @@
package com.baiyue.iam.service;
import com.baiyue.iam.dto.OnboardingDtos.QualificationSubmissionRequest;
import com.baiyue.iam.dto.OnboardingDtos.RequiredQualificationPackageRequest;
import com.baiyue.iam.entity.IamTenant;
import com.baiyue.iam.repository.ProfileResourceRepository;
import com.baiyue.iam.repository.TenantRepository;
@@ -18,12 +19,13 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.times;
import com.baiyue.common.core.exception.BizException;
class MerchantQualificationUploadTest {
@Test
void uploadsOneDraftQualificationWithoutCreatingAReview() {
void uploadsOneOptionalDraftQualificationWithoutCreatingAReview() {
TenantRepository tenantRepository = mock(TenantRepository.class);
ProfileResourceRepository profileRepository = mock(ProfileResourceRepository.class);
ProfileResourceService service = new ProfileResourceService();
@@ -37,8 +39,8 @@ class MerchantQualificationUploadTest {
when(profileRepository.findQualificationsForUpdate(10001L)).thenReturn(List.of());
var response = service.submitQualification(new QualificationSubmissionRequest(
10001L, "LEGAL_PERSON_ID", null,
"/api/merchant/v1/files/qualifications/legal-person.png", LocalDate.of(2030, 1, 1), false));
10001L, "FREIGHT_FORWARDER_CERTIFICATE", null,
"/api/merchant/v1/files/qualifications/freight-forwarder.png", LocalDate.of(2030, 1, 1), false));
assertEquals("PROFILE_REQUIRED", response.tenantStatus());
assertNull(response.reviewId());
@@ -47,7 +49,26 @@ class MerchantQualificationUploadTest {
}
@Test
void businessLicenseRequiresAndPersistsAUniqueUnifiedSocialCreditCode() {
void requiredQualificationsRejectTheLegacySingleFilePath() {
TenantRepository tenantRepository = mock(TenantRepository.class);
ProfileResourceRepository profileRepository = mock(ProfileResourceRepository.class);
ProfileResourceService service = new ProfileResourceService();
ReflectionTestUtils.setField(service, "tenantRepository", tenantRepository);
ReflectionTestUtils.setField(service, "repository", profileRepository);
IamTenant tenant = new IamTenant();
tenant.setId(10001L);
tenant.setTenantType("MERCHANT");
tenant.setStatus("PROFILE_REQUIRED");
when(tenantRepository.findTenantForUpdate(10001L)).thenReturn(tenant);
assertThrows(BizException.class, () -> service.submitQualification(new QualificationSubmissionRequest(
10001L, "BUSINESS_LICENSE", "91310101abcde12345",
"/api/merchant/v1/files/qualifications/license.png", null, false)));
verify(profileRepository, never()).insertQualification(any());
}
@Test
void requiredPackagePersistsBothFilesAndCreditCodeTogether() {
TenantRepository tenantRepository = mock(TenantRepository.class);
ProfileResourceRepository profileRepository = mock(ProfileResourceRepository.class);
ProfileResourceService service = new ProfileResourceService();
@@ -60,21 +81,19 @@ class MerchantQualificationUploadTest {
when(tenantRepository.findTenantForUpdate(10001L)).thenReturn(tenant);
when(profileRepository.findQualificationsForUpdate(10001L)).thenReturn(List.of());
assertThrows(BizException.class, () -> service.submitQualification(new QualificationSubmissionRequest(
10001L, "BUSINESS_LICENSE", null,
"/api/merchant/v1/files/qualifications/license.png", null, false)));
var response = service.submitQualification(new QualificationSubmissionRequest(
10001L, "BUSINESS_LICENSE", "91310101abcde12345",
"/api/merchant/v1/files/qualifications/license.png", null, false));
var response = service.submitRequiredQualificationPackage(new RequiredQualificationPackageRequest(
10001L, "91310101abcde12345",
"/api/merchant/v1/files/qualifications/license.png", null, false,
"/api/merchant/v1/files/qualifications/legal-person.png", null, false));
assertEquals("PROFILE_REQUIRED", response.tenantStatus());
assertEquals("91310101ABCDE12345", tenant.getUnifiedSocialCreditCode());
verify(profileRepository, times(2)).insertQualification(any());
verify(tenantRepository).saveTenant(tenant);
}
@Test
void businessLicenseCannotOverwriteAnEstablishedCreditCode() {
void requiredPackageCannotOverwriteAnEstablishedCreditCode() {
TenantRepository tenantRepository = mock(TenantRepository.class);
ProfileResourceRepository profileRepository = mock(ProfileResourceRepository.class);
ProfileResourceService service = new ProfileResourceService();
@@ -87,11 +106,11 @@ class MerchantQualificationUploadTest {
tenant.setUnifiedSocialCreditCode("91330100EXAMPLE001");
when(tenantRepository.findTenantForUpdate(10001L)).thenReturn(tenant);
assertThrows(BizException.class, () -> service.submitQualification(new QualificationSubmissionRequest(
10001L, "BUSINESS_LICENSE", "91310101ABCDE12345",
"/api/merchant/v1/files/qualifications/license.png", null, true)));
assertThrows(BizException.class, () -> service.submitRequiredQualificationPackage(
new RequiredQualificationPackageRequest(10001L, "91310101ABCDE12345",
"/api/merchant/v1/files/qualifications/license.png", null, true,
"/api/merchant/v1/files/qualifications/legal-person.png", null, true)));
verify(profileRepository, never()).insertQualification(any());
verify(tenantRepository, never()).saveTenant(tenant);
}
}
@@ -21,7 +21,7 @@ import static org.mockito.Mockito.when;
class PlatformQualificationRegistrationTest {
@Test
void platformUploadRegistersMetadataWithoutCreatingReviewTicket() {
void platformUploadRegistersOptionalMetadataWithoutCreatingReviewTicket() {
ProfileResourceRepository repository = mock(ProfileResourceRepository.class);
TenantRepository tenantRepository = mock(TenantRepository.class);
ProfileResourceService service = new ProfileResourceService();
@@ -33,13 +33,13 @@ class PlatformQualificationRegistrationTest {
when(repository.findQualificationsForUpdate(10001L)).thenReturn(List.of());
var response = service.registerPlatformQualification(new PlatformQualificationRegistrationRequest(
10001L, "LEGAL_PERSON_ID", null, "/api/merchant/v1/files/qualifications/file.pdf",
10001L, "BANK_ACCOUNT_LICENSE", null, "/api/merchant/v1/files/qualifications/file.pdf",
LocalDate.of(2030, 12, 31), false));
ArgumentCaptor<IamTenantQualification> captor = ArgumentCaptor.forClass(IamTenantQualification.class);
verify(repository).insertQualification(captor.capture());
verify(repository).saveQualification(captor.getValue());
assertEquals("LEGAL_PERSON_ID", captor.getValue().getQualificationType());
assertEquals("BANK_ACCOUNT_LICENSE", captor.getValue().getQualificationType());
assertEquals(LocalDate.of(2030, 12, 31), captor.getValue().getValidTo());
assertEquals("PROFILE_REQUIRED", response.tenantStatus());
assertNull(response.reviewId());
@@ -56,14 +56,14 @@ class PlatformQualificationRegistrationTest {
IamTenant tenant = new IamTenant();
tenant.setId(10001L); tenant.setTenantType("MERCHANT"); tenant.setStatus("PROFILE_REQUIRED");
IamTenantQualification existing = new IamTenantQualification();
existing.setId(88L); existing.setTenantId(10001L); existing.setQualificationType("LEGAL_PERSON_ID");
existing.setId(88L); existing.setTenantId(10001L); existing.setQualificationType("BANK_ACCOUNT_LICENSE");
existing.setStatus("PENDING");
existing.setDocumentUrl("/api/merchant/v1/files/qualifications/old-file.pdf");
when(tenantRepository.findTenantForUpdate(10001L)).thenReturn(tenant);
when(repository.findQualificationsForUpdate(10001L)).thenReturn(List.of(existing));
var response = service.registerPlatformQualification(new PlatformQualificationRegistrationRequest(
10001L, "LEGAL_PERSON_ID", null, "/api/merchant/v1/files/qualifications/new-file.pdf",
10001L, "BANK_ACCOUNT_LICENSE", null, "/api/merchant/v1/files/qualifications/new-file.pdf",
LocalDate.of(2031, 12, 31), true));
ArgumentCaptor<IamTenantQualification> captor = ArgumentCaptor.forClass(IamTenantQualification.class);
@@ -120,7 +120,7 @@ class TenantServiceTest {
ReflectionTestUtils.setField(service, "repository", repository);
var created = service.register(new RegisterRequest(
"Example Merchant", "Example Merchant Ltd", "Bob", "91330100EXAMPLE001", "Alice", "13800138000",
"Example Merchant", "Example Merchant Ltd", "Bob", "Alice", "13800138000",
"alice@example.com", "基础版", "alice_wechat", "Sales Zhang", 30, "LIMITED_COMPANY",
LocalDate.of(2020, 1, 2), new BigDecimal("5000000.00"), "CNY", "深圳市南山区", "草稿客户"),
9001L);
@@ -134,13 +134,13 @@ class TenantServiceTest {
}
@Test
void platformRegistrationAllowsCreditCodeToBeCompletedWithQualificationsLater() {
void platformRegistrationAlwaysCreatesTheDraftWithoutACreditCode() {
TenantRepository repository = mock(TenantRepository.class);
TenantService service = new TenantService();
ReflectionTestUtils.setField(service, "repository", repository);
var created = service.register(new RegisterRequest(
"Example Merchant", "Example Merchant Ltd", "Bob", null, "Alice", "13800138000",
"Example Merchant", "Example Merchant Ltd", "Bob", "Alice", "13800138000",
"alice@example.com", "基础版", null, null, 30, null,
null, null, "CNY", null, null), 9001L);