diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientKycRepository.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientKycRepository.java index 7d7ea590d..13bb92607 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientKycRepository.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientKycRepository.java @@ -35,4 +35,31 @@ public interface ClientKycRepository extends JpaRepository { @Query("SELECT k FROM ClientKyc k WHERE k.kycStatus = :status") List findAllByStatus(@Param("status") Integer status); + + // ── Pre-KYC uniqueness probes ─────────────────────────────────────────── + // Why: stop a second client from being created with the same PAN / Aadhaar / GSTIN BEFORE the + // external KYC API is called, so we don't burn vendor calls on duplicate-identity records. PAN + // and GSTIN match exact upper-cased; Aadhaar is compared masked-form (only last 4 are stored). + // Two variants per field — one for create (no row to exclude), one for update (exclude self) — + // to avoid PostgreSQL's bigint <> varchar parse error on a null Long parameter. + @Query("SELECT CASE WHEN COUNT(k) > 0 THEN true ELSE false END FROM ClientKyc k WHERE UPPER(k.panNumber) = UPPER(:panNumber)") + boolean existsByPanNumber(@Param("panNumber") String panNumber); + + @Query("SELECT CASE WHEN COUNT(k) > 0 THEN true ELSE false END FROM ClientKyc k " + + "WHERE UPPER(k.panNumber) = UPPER(:panNumber) AND k.client.id <> :excludeClientId") + boolean existsByPanNumberExcluding(@Param("panNumber") String panNumber, @Param("excludeClientId") Long excludeClientId); + + @Query("SELECT CASE WHEN COUNT(k) > 0 THEN true ELSE false END FROM ClientKyc k WHERE k.aadhaarNumberMasked = :aadhaarMasked") + boolean existsByAadhaarMasked(@Param("aadhaarMasked") String aadhaarMasked); + + @Query("SELECT CASE WHEN COUNT(k) > 0 THEN true ELSE false END FROM ClientKyc k " + + "WHERE k.aadhaarNumberMasked = :aadhaarMasked AND k.client.id <> :excludeClientId") + boolean existsByAadhaarMaskedExcluding(@Param("aadhaarMasked") String aadhaarMasked, @Param("excludeClientId") Long excludeClientId); + + @Query("SELECT CASE WHEN COUNT(k) > 0 THEN true ELSE false END FROM ClientKyc k WHERE UPPER(k.gstinNumber) = UPPER(:gstinNumber)") + boolean existsByGstinNumber(@Param("gstinNumber") String gstinNumber); + + @Query("SELECT CASE WHEN COUNT(k) > 0 THEN true ELSE false END FROM ClientKyc k " + + "WHERE UPPER(k.gstinNumber) = UPPER(:gstinNumber) AND k.client.id <> :excludeClientId") + boolean existsByGstinNumberExcluding(@Param("gstinNumber") String gstinNumber, @Param("excludeClientId") Long excludeClientId); } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepository.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepository.java index ae6ee9af7..47b662553 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepository.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepository.java @@ -61,4 +61,25 @@ public interface ClientRepository extends JpaRepository, JpaSpecif */ @Query("SELECT COUNT(c) FROM Client c WHERE c.cifNumber LIKE CONCAT(:prefix, '%')") long countByCifNumberPrefix(@Param("prefix") String prefix); + + // ── Pre-save uniqueness probes ─────────────────────────────────────────── + // Why: DB has UNIQUE on mobile_no / email_address, but we want to fail fast with a clear + // field-level error BEFORE saveAndFlush — and importantly before the external KYC API call. + // Two variants on each: create-time has no row to exclude; update-time excludes the row being + // edited so it doesn't conflict with itself. Splitting avoids the bigint <> varchar JPQL bug + // PostgreSQL throws when a null Long parameter is parsed as varchar at prepare-time. + @Query("SELECT CASE WHEN COUNT(c) > 0 THEN true ELSE false END FROM Client c WHERE c.mobileNo = :mobileNo") + boolean existsByMobileNo(@Param("mobileNo") String mobileNo); + + @Query("SELECT CASE WHEN COUNT(c) > 0 THEN true ELSE false END FROM Client c " + + "WHERE c.mobileNo = :mobileNo AND c.id <> :excludeClientId") + boolean existsByMobileNoExcluding(@Param("mobileNo") String mobileNo, @Param("excludeClientId") Long excludeClientId); + + @Query("SELECT CASE WHEN COUNT(c) > 0 THEN true ELSE false END FROM Client c " + + "WHERE LOWER(c.emailAddress) = LOWER(:emailAddress)") + boolean existsByEmailAddress(@Param("emailAddress") String emailAddress); + + @Query("SELECT CASE WHEN COUNT(c) > 0 THEN true ELSE false END FROM Client c " + + "WHERE LOWER(c.emailAddress) = LOWER(:emailAddress) AND c.id <> :excludeClientId") + boolean existsByEmailAddressExcluding(@Param("emailAddress") String emailAddress, @Param("excludeClientId") Long excludeClientId); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index 679e1255f..27f81563e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -67,7 +67,9 @@ import org.apache.fineract.portfolio.client.data.ClientDataValidator; import org.apache.fineract.portfolio.client.domain.Client; import org.apache.fineract.portfolio.client.domain.ClientEnumerations; import org.apache.fineract.portfolio.client.domain.ClientNonPerson; +import org.apache.fineract.portfolio.client.domain.ClientKycRepository; import org.apache.fineract.portfolio.client.domain.ClientNonPersonRepositoryWrapper; +import org.apache.fineract.portfolio.client.domain.ClientRepository; import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; import org.apache.fineract.portfolio.client.domain.ClientStatus; import org.apache.fineract.portfolio.client.domain.LegalForm; @@ -125,6 +127,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP private final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService; private final ExternalIdFactory externalIdFactory; private final ClientKycWritePlatformService clientKycWritePlatformService; + private final ClientKycRepository clientKycRepository; + private final ClientRepository clientJpaRepository; private final org.apache.fineract.portfolio.mobilelookup.domain.MobileLookupLogRepository mobileLookupLogRepository; private final org.apache.fineract.portfolio.sanctions.domain.SanctionsScreeningLogRepository sanctionsScreeningLogRepository; private final CifNumberGenerator cifNumberGenerator; @@ -189,6 +193,97 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP "Unknown data integrity issue with resource: " + realCause.getMessage()); } + /** + * Rejects a save when any uniqueness-relevant field (mobile/email on the client row, PAN/Aadhaar/ + * GSTIN on the KYC row) already exists on another active client. Runs BEFORE saveAndFlush and + * BEFORE the external KYC API call, so the vendor isn't billed on duplicate-identity records. + * + * @param command the JsonCommand carrying the client payload (PAN/Aadhaar/GSTIN nested + * under the {@code kyc} object) + * @param excludeClientId {@code null} on create; the row id on update so a row doesn't conflict + * with itself + */ + private void validateClientUniqueness(final JsonCommand command, final Long excludeClientId) { + final String mobileNo = command.stringValueOfParameterNamed(ClientApiConstants.mobileNoParamName); + if (StringUtils.isNotBlank(mobileNo)) { + final boolean clash = excludeClientId == null + ? clientJpaRepository.existsByMobileNo(mobileNo) + : clientJpaRepository.existsByMobileNoExcluding(mobileNo, excludeClientId); + if (clash) { + throw new PlatformDataIntegrityException("error.msg.client.duplicate.mobileNo", + "Client with mobileNo `" + mobileNo + "` already exists", "mobileNo", mobileNo); + } + } + + final String emailAddress = command.stringValueOfParameterNamed(ClientApiConstants.emailAddressParamName); + if (StringUtils.isNotBlank(emailAddress)) { + final boolean clash = excludeClientId == null + ? clientJpaRepository.existsByEmailAddress(emailAddress) + : clientJpaRepository.existsByEmailAddressExcluding(emailAddress, excludeClientId); + if (clash) { + throw new PlatformDataIntegrityException("error.msg.client.duplicate.emailAddress", + "Client with emailAddress `" + emailAddress + "` already exists", "emailAddress", emailAddress); + } + } + + // KYC fields are nested under "kyc" in the create/update payload — pull them out manually. + final JsonElement root = this.fromApiJsonHelper.parse(command.json()); + if (root == null || !root.isJsonObject()) { + return; + } + final JsonElement kyc = root.getAsJsonObject().get(ClientApiConstants.kycParamName); + if (kyc == null || kyc.isJsonNull() || !kyc.isJsonObject()) { + return; + } + + final String pan = this.fromApiJsonHelper.extractStringNamed( + org.apache.fineract.portfolio.client.data.ClientKycApiConstants.panNumberParam, kyc); + if (StringUtils.isNotBlank(pan)) { + final boolean clash = excludeClientId == null + ? clientKycRepository.existsByPanNumber(pan) + : clientKycRepository.existsByPanNumberExcluding(pan, excludeClientId); + if (clash) { + throw new PlatformDataIntegrityException("error.msg.client.kyc.duplicate.panNumber", + "A client with PAN `" + pan + "` already exists. PAN must be unique across clients.", + "panNumber", pan); + } + } + + // Aadhaar uniqueness: the request carries either the masked form (already trimmed to last-4) + // or the full 12-digit number to be sent to the OTP vendor. We compare against the masked + // column either way — for a full number, mask the leading 8 digits first. + String aadhaar = this.fromApiJsonHelper.extractStringNamed( + org.apache.fineract.portfolio.client.data.ClientKycApiConstants.aadhaarNumberMaskedParam, kyc); + if (StringUtils.isBlank(aadhaar)) { + aadhaar = this.fromApiJsonHelper.extractStringNamed( + org.apache.fineract.portfolio.client.data.ClientKycApiConstants.aadhaarNumberParam, kyc); + } + if (StringUtils.isNotBlank(aadhaar)) { + final String masked = aadhaar.length() == 12 ? "XXXXXXXX" + aadhaar.substring(8) : aadhaar; + final boolean clash = excludeClientId == null + ? clientKycRepository.existsByAadhaarMasked(masked) + : clientKycRepository.existsByAadhaarMaskedExcluding(masked, excludeClientId); + if (clash) { + throw new PlatformDataIntegrityException("error.msg.client.kyc.duplicate.aadhaar", + "A client with this Aadhaar already exists. Aadhaar must be unique across clients.", + "aadhaarNumber", masked); + } + } + + final String gstin = this.fromApiJsonHelper.extractStringNamed( + org.apache.fineract.portfolio.client.data.ClientKycApiConstants.gstinNumberParam, kyc); + if (StringUtils.isNotBlank(gstin)) { + final boolean clash = excludeClientId == null + ? clientKycRepository.existsByGstinNumber(gstin) + : clientKycRepository.existsByGstinNumberExcluding(gstin, excludeClientId); + if (clash) { + throw new PlatformDataIntegrityException("error.msg.client.kyc.duplicate.gstin", + "A client with GSTIN `" + gstin + "` already exists. GSTIN must be unique across clients.", + "gstinNumber", gstin); + } + } + } + @Transactional @Override public CommandProcessingResult createClient(final JsonCommand command) { @@ -198,6 +293,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP this.fromApiJsonDeserializer.validateForCreate(command.json()); + // Reject duplicates BEFORE save AND before the external KYC API call further down — we + // don't want to burn vendor credits on identity-duplicate records. + validateClientUniqueness(command, null); + final Boolean isAddressEnabled = configurationDomainService.isAddressEnabled(); final Long officeId = command.longValueOfParameterNamed(ClientApiConstants.officeIdParamName); @@ -637,6 +736,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP this.context.validateAccessRights(clientHierarchy); + // Same duplicate guard as createClient — exclude the current row so non-uniqueness + // changes (e.g. address-only update) don't trip the check against itself. + validateClientUniqueness(command, clientId); + final Map changes = new LinkedHashMap<>(9); if (command.isChangeInIntegerParameterNamed(ClientApiConstants.statusParamName, clientForUpdate.getStatus())) { diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index 86f401624..e668bfb28 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -308,4 +308,5 @@ + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0297_seed_indian_states.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0297_seed_indian_states.xml new file mode 100644 index 000000000..2fe195058 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0297_seed_indian_states.xml @@ -0,0 +1,294 @@ + + + + + + + + + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id + WHERE c.code_name = 'STATE' AND cv.code_value = 'MAHARASHTRA' + + + + + + code_value = 'MAHARASHTRA' + AND code_id = (SELECT id FROM m_code WHERE code_name = 'STATE') + + + + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id + WHERE c.code_name = 'STATE' AND cv.code_value = 'MADHYA_PRADESH' + + + + + + code_value = 'MADHYA_PRADESH' + AND code_id = (SELECT id FROM m_code WHERE code_name = 'STATE') + + + + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id + WHERE c.code_name = 'STATE' AND cv.code_value = 'DELHI' + + + + + + code_value = 'DELHI' + AND code_id = (SELECT id FROM m_code WHERE code_name = 'STATE') + + + + + + + + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Andhra Pradesh' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Andhra Pradesh', 'Indian State', 1, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Arunachal Pradesh' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Arunachal Pradesh', 'Indian State', 2, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Assam' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Assam', 'Indian State', 3, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Bihar' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Bihar', 'Indian State', 4, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Chhattisgarh' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Chhattisgarh', 'Indian State', 5, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Goa' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Goa', 'Indian State', 6, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Gujarat' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Gujarat', 'Indian State', 7, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Haryana' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Haryana', 'Indian State', 8, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Himachal Pradesh' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Himachal Pradesh', 'Indian State', 9, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Jharkhand' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Jharkhand', 'Indian State', 10, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Karnataka' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Karnataka', 'Indian State', 11, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Kerala' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Kerala', 'Indian State', 12, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Manipur' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Manipur', 'Indian State', 15, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Meghalaya' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Meghalaya', 'Indian State', 16, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Mizoram' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Mizoram', 'Indian State', 17, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Nagaland' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Nagaland', 'Indian State', 18, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Odisha' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Odisha', 'Indian State', 19, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Punjab' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Punjab', 'Indian State', 20, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Rajasthan' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Rajasthan', 'Indian State', 21, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Sikkim' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Sikkim', 'Indian State', 22, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Tamil Nadu' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Tamil Nadu', 'Indian State', 23, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Telangana' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Telangana', 'Indian State', 24, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Tripura' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Tripura', 'Indian State', 25, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Uttar Pradesh' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Uttar Pradesh', 'Indian State', 26, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Uttarakhand' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Uttarakhand', 'Indian State', 27, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'West Bengal' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'West Bengal', 'Indian State', 28, true, false FROM m_code WHERE code_name = 'STATE' + + + + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Andaman and Nicobar Islands' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Andaman and Nicobar Islands', 'Union Territory', 29, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Chandigarh' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Chandigarh', 'Union Territory', 30, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Dadra and Nagar Haveli and Daman and Diu' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Dadra and Nagar Haveli and Daman and Diu', 'Union Territory', 31, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Jammu and Kashmir' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Jammu and Kashmir', 'Union Territory', 33, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Ladakh' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Ladakh', 'Union Territory', 34, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Lakshadweep' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Lakshadweep', 'Union Territory', 35, true, false FROM m_code WHERE code_name = 'STATE' + + + + SELECT COUNT(*) FROM m_code_value cv JOIN m_code c ON cv.code_id = c.id WHERE c.code_name = 'STATE' AND cv.code_value = 'Puducherry' + + INSERT INTO m_code_value (code_id, code_value, code_description, order_position, is_active, is_mandatory) SELECT id, 'Puducherry', 'Union Territory', 36, true, false FROM m_code WHERE code_name = 'STATE' + + +