List of usage examples for org.springframework.dao DataIntegrityViolationException getCause
public synchronized Throwable getCause()
From source file:com.gst.portfolio.client.service.ClientWritePlatformServiceJpaRepositoryImpl.java
@Transactional @Override/*w w w .j av a 2s .c o m*/ public CommandProcessingResult createClient(final JsonCommand command) { try { final AppUser currentUser = this.context.authenticatedUser(); this.fromApiJsonDeserializer.validateForCreate(command.json()); final GlobalConfigurationPropertyData configuration = this.configurationReadPlatformService .retrieveGlobalConfiguration("Enable-Address"); final Boolean isAddressEnabled = configuration.isEnabled(); final Long officeId = command.longValueOfParameterNamed(ClientApiConstants.officeIdParamName); final Office clientOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(officeId); final Long groupId = command.longValueOfParameterNamed(ClientApiConstants.groupIdParamName); Group clientParentGroup = null; if (groupId != null) { clientParentGroup = this.groupRepository.findOne(groupId); if (clientParentGroup == null) { throw new GroupNotFoundException(groupId); } } Staff staff = null; final Long staffId = command.longValueOfParameterNamed(ClientApiConstants.staffIdParamName); if (staffId != null) { staff = this.staffRepository.findByOfficeHierarchyWithNotFoundDetection(staffId, clientOffice.getHierarchy()); } CodeValue gender = null; final Long genderId = command.longValueOfParameterNamed(ClientApiConstants.genderIdParamName); if (genderId != null) { gender = this.codeValueRepository .findOneByCodeNameAndIdWithNotFoundDetection(ClientApiConstants.GENDER, genderId); } CodeValue clientType = null; final Long clientTypeId = command.longValueOfParameterNamed(ClientApiConstants.clientTypeIdParamName); if (clientTypeId != null) { clientType = this.codeValueRepository .findOneByCodeNameAndIdWithNotFoundDetection(ClientApiConstants.CLIENT_TYPE, clientTypeId); } CodeValue clientClassification = null; final Long clientClassificationId = command .longValueOfParameterNamed(ClientApiConstants.clientClassificationIdParamName); if (clientClassificationId != null) { clientClassification = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection( ClientApiConstants.CLIENT_CLASSIFICATION, clientClassificationId); } final Long savingsProductId = command .longValueOfParameterNamed(ClientApiConstants.savingsProductIdParamName); if (savingsProductId != null) { SavingsProduct savingsProduct = this.savingsProductRepository.findOne(savingsProductId); if (savingsProduct == null) { throw new SavingsProductNotFoundException(savingsProductId); } } final Integer legalFormParamValue = command .integerValueOfParameterNamed(ClientApiConstants.legalFormIdParamName); boolean isEntity = false; Integer legalFormValue = null; if (legalFormParamValue != null) { LegalForm legalForm = LegalForm.fromInt(legalFormParamValue); if (legalForm != null) { legalFormValue = legalForm.getValue(); isEntity = legalForm.isEntity(); } } final Client newClient = Client.createNew(currentUser, clientOffice, clientParentGroup, staff, savingsProductId, gender, clientType, clientClassification, legalFormValue, command); this.clientRepository.save(newClient); boolean rollbackTransaction = false; if (newClient.isActive()) { validateParentGroupRulesBeforeClientActivation(newClient); runEntityDatatableCheck(newClient.getId()); final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateClient(null).build(); rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser); } this.clientRepository.save(newClient); if (newClient.isActive()) { this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_ACTIVATE, constructEntityMap(BUSINESS_ENTITY.CLIENT, newClient)); } if (newClient.isAccountNumberRequiresAutoGeneration()) { AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository .findByAccountType(EntityAccountType.CLIENT); newClient.updateAccountNo(accountNumberGenerator.generate(newClient, accountNumberFormat)); this.clientRepository.save(newClient); } final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale); CommandProcessingResult result = openSavingsAccount(newClient, fmt); if (result.getSavingsId() != null) { this.clientRepository.save(newClient); } if (isEntity) { extractAndCreateClientNonPerson(newClient, command); } if (isAddressEnabled) { this.addressWritePlatformService.addNewClientAddress(newClient, command); } if (command.parameterExists(ClientApiConstants.datatables)) { this.entityDatatableChecksWritePlatformService.saveDatatables( StatusEnum.CREATE.getCode().longValue(), EntityTables.CLIENT.getName(), newClient.getId(), null, command.arrayOfParameterNamed(ClientApiConstants.datatables)); } this.entityDatatableChecksWritePlatformService.runTheCheck(newClient.getId(), EntityTables.CLIENT.getName(), StatusEnum.CREATE.getCode().longValue(), EntityTables.CLIENT.getForeignKeyColumnNameOnDatatable()); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withOfficeId(clientOffice.getId()) // .withClientId(newClient.getId()) // .withGroupId(groupId) // .withEntityId(newClient.getId()) // .withSavingsId(result.getSavingsId())// .setRollbackTransaction(rollbackTransaction)// .setRollbackTransaction(result.isRollbackTransaction())// .build(); } catch (final DataIntegrityViolationException dve) { handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); return CommandProcessingResult.empty(); } catch (final PersistenceException dve) { Throwable throwable = ExceptionUtils.getRootCause(dve.getCause()); handleDataIntegrityIssues(command, throwable, dve); return CommandProcessingResult.empty(); } }
From source file:com.gst.portfolio.group.service.GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
private CommandProcessingResult updateGroupingType(final Long groupId, final JsonCommand command, final GroupTypes groupingType) { try {//from w w w .j a v a 2s. c o m this.context.authenticatedUser(); final Group groupForUpdate = this.groupRepository.findOneWithNotFoundDetection(groupId); final Long officeId = groupForUpdate.officeId(); final Office groupOffice = groupForUpdate.getOffice(); final String groupHierarchy = groupOffice.getHierarchy(); this.context.validateAccessRights(groupHierarchy); final LocalDate activationDate = command .localDateValueOfParameterNamed(GroupingTypesApiConstants.activationDateParamName); validateOfficeOpeningDateisAfterGroupOrCenterOpeningDate(groupOffice, groupForUpdate.getGroupLevel(), activationDate); final Map<String, Object> actualChanges = groupForUpdate.update(command); if (actualChanges.containsKey(GroupingTypesApiConstants.staffIdParamName)) { final Long newValue = command.longValueOfParameterNamed(GroupingTypesApiConstants.staffIdParamName); Staff newStaff = null; if (newValue != null) { newStaff = this.staffRepository.findByOfficeHierarchyWithNotFoundDetection(newValue, groupHierarchy); } groupForUpdate.updateStaff(newStaff); } final GroupLevel groupLevel = this.groupLevelRepository.findOne(groupForUpdate.getGroupLevel().getId()); /* * Ignoring parentId param, if group for update is super parent. * TODO Need to check: Ignoring is correct or need throw unsupported * param */ if (!groupLevel.isSuperParent()) { Long parentId = null; final Group presentParentGroup = groupForUpdate.getParent(); if (presentParentGroup != null) { parentId = presentParentGroup.getId(); } if (command.isChangeInLongParameterNamed(GroupingTypesApiConstants.centerIdParamName, parentId)) { final Long newValue = command .longValueOfParameterNamed(GroupingTypesApiConstants.centerIdParamName); actualChanges.put(GroupingTypesApiConstants.centerIdParamName, newValue); Group newParentGroup = null; if (newValue != null) { newParentGroup = this.groupRepository.findOneWithNotFoundDetection(newValue); if (!newParentGroup.isOfficeIdentifiedBy(officeId)) { final String errorMessage = "Group and parent group must have the same office"; throw new InvalidOfficeException("group", "attach.to.parent.group", errorMessage); } /* * If Group is not super parent then validate group * level's parent level is same as group parent's level * this check makes sure new group is added at immediate * next level in hierarchy */ if (!groupForUpdate.getGroupLevel() .isIdentifiedByParentId(newParentGroup.getGroupLevel().getId())) { final String errorMessage = "Parent group's level is not equal to child level's parent level "; throw new InvalidGroupLevelException("add", "invalid.level", errorMessage); } } groupForUpdate.setParent(newParentGroup); // Parent has changed, re-generate 'Hierarchy' as parent is // changed groupForUpdate.generateHierarchy(); } } /* * final Set<Client> clientMembers = assembleSetOfClients(officeId, * command); List<String> changes = * groupForUpdate.updateClientMembersIfDifferent(clientMembers); if * (!changes.isEmpty()) { * actualChanges.put(GroupingTypesApiConstants * .clientMembersParamName, changes); } */ this.groupRepository.saveAndFlush(groupForUpdate); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withOfficeId(groupForUpdate.officeId()) // .withGroupId(groupForUpdate.getId()) // .withEntityId(groupForUpdate.getId()) // .with(actualChanges) // .build(); } catch (final DataIntegrityViolationException dve) { handleGroupDataIntegrityIssues(command, dve.getMostSpecificCause(), dve, groupingType); return CommandProcessingResult.empty(); } catch (final PersistenceException dve) { Throwable throwable = ExceptionUtils.getRootCause(dve.getCause()); handleGroupDataIntegrityIssues(command, throwable, dve, groupingType); return CommandProcessingResult.empty(); } }
From source file:com.gst.portfolio.client.service.ClientWritePlatformServiceJpaRepositoryImpl.java
@Transactional @Override//from ww w . java 2 s .c o m public CommandProcessingResult updateClient(final Long clientId, final JsonCommand command) { try { this.fromApiJsonDeserializer.validateForUpdate(command.json()); final Client clientForUpdate = this.clientRepository.findOneWithNotFoundDetection(clientId); final String clientHierarchy = clientForUpdate.getOffice().getHierarchy(); this.context.validateAccessRights(clientHierarchy); final Map<String, Object> changes = clientForUpdate.update(command); if (changes.containsKey(ClientApiConstants.staffIdParamName)) { final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.staffIdParamName); Staff newStaff = null; if (newValue != null) { newStaff = this.staffRepository.findByOfficeHierarchyWithNotFoundDetection(newValue, clientForUpdate.getOffice().getHierarchy()); } clientForUpdate.updateStaff(newStaff); } if (changes.containsKey(ClientApiConstants.genderIdParamName)) { final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.genderIdParamName); CodeValue gender = null; if (newValue != null) { gender = this.codeValueRepository .findOneByCodeNameAndIdWithNotFoundDetection(ClientApiConstants.GENDER, newValue); } clientForUpdate.updateGender(gender); } if (changes.containsKey(ClientApiConstants.savingsProductIdParamName)) { if (clientForUpdate.isActive()) { throw new ClientActiveForUpdateException(clientId, ClientApiConstants.savingsProductIdParamName); } SavingsProduct savingsProduct = null; final Long savingsProductId = command .longValueOfParameterNamed(ClientApiConstants.savingsProductIdParamName); if (savingsProductId != null) { savingsProduct = this.savingsProductRepository.findOne(savingsProductId); if (savingsProduct == null) { throw new SavingsProductNotFoundException(savingsProductId); } } clientForUpdate.updateSavingsProduct(savingsProductId); } if (changes.containsKey(ClientApiConstants.genderIdParamName)) { final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.genderIdParamName); CodeValue newCodeVal = null; if (newValue != null) { newCodeVal = this.codeValueRepository .findOneByCodeNameAndIdWithNotFoundDetection(ClientApiConstants.GENDER, newValue); } clientForUpdate.updateGender(newCodeVal); } if (changes.containsKey(ClientApiConstants.clientTypeIdParamName)) { final Long newValue = command.longValueOfParameterNamed(ClientApiConstants.clientTypeIdParamName); CodeValue newCodeVal = null; if (newValue != null) { newCodeVal = this.codeValueRepository .findOneByCodeNameAndIdWithNotFoundDetection(ClientApiConstants.CLIENT_TYPE, newValue); } clientForUpdate.updateClientType(newCodeVal); } if (changes.containsKey(ClientApiConstants.clientClassificationIdParamName)) { final Long newValue = command .longValueOfParameterNamed(ClientApiConstants.clientClassificationIdParamName); CodeValue newCodeVal = null; if (newValue != null) { newCodeVal = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection( ClientApiConstants.CLIENT_CLASSIFICATION, newValue); } clientForUpdate.updateClientClassification(newCodeVal); } if (!changes.isEmpty()) { this.clientRepository.saveAndFlush(clientForUpdate); } if (changes.containsKey(ClientApiConstants.legalFormIdParamName)) { Integer legalFormValue = clientForUpdate.getLegalForm(); boolean isChangedToEntity = false; if (legalFormValue != null) { LegalForm legalForm = LegalForm.fromInt(legalFormValue); if (legalForm != null) isChangedToEntity = legalForm.isEntity(); } if (isChangedToEntity) { extractAndCreateClientNonPerson(clientForUpdate, command); } else { final ClientNonPerson clientNonPerson = this.clientNonPersonRepository .findOneByClientId(clientForUpdate.getId()); if (clientNonPerson != null) this.clientNonPersonRepository.delete(clientNonPerson); } } final ClientNonPerson clientNonPersonForUpdate = this.clientNonPersonRepository .findOneByClientId(clientId); if (clientNonPersonForUpdate != null) { final JsonElement clientNonPersonElement = this.fromApiJsonHelper .parse(command.jsonFragment(ClientApiConstants.clientNonPersonDetailsParamName)); final Map<String, Object> clientNonPersonChanges = clientNonPersonForUpdate .update(JsonCommand.fromExistingCommand(command, clientNonPersonElement)); if (clientNonPersonChanges.containsKey(ClientApiConstants.constitutionIdParamName)) { final Long newValue = this.fromApiJsonHelper .extractLongNamed(ClientApiConstants.constitutionIdParamName, clientNonPersonElement); CodeValue constitution = null; if (newValue != null) { constitution = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection( ClientApiConstants.CLIENT_NON_PERSON_CONSTITUTION, newValue); } clientNonPersonForUpdate.updateConstitution(constitution); } if (clientNonPersonChanges.containsKey(ClientApiConstants.mainBusinessLineIdParamName)) { final Long newValue = this.fromApiJsonHelper.extractLongNamed( ClientApiConstants.mainBusinessLineIdParamName, clientNonPersonElement); CodeValue mainBusinessLine = null; if (newValue != null) { mainBusinessLine = this.codeValueRepository.findOneByCodeNameAndIdWithNotFoundDetection( ClientApiConstants.CLIENT_NON_PERSON_MAIN_BUSINESS_LINE, newValue); } clientNonPersonForUpdate.updateMainBusinessLine(mainBusinessLine); } if (!clientNonPersonChanges.isEmpty()) { this.clientNonPersonRepository.saveAndFlush(clientNonPersonForUpdate); } changes.putAll(clientNonPersonChanges); } return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withOfficeId(clientForUpdate.officeId()) // .withClientId(clientId) // .withEntityId(clientId) // .with(changes) // .build(); } catch (final DataIntegrityViolationException dve) { handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); return CommandProcessingResult.empty(); } catch (final PersistenceException dve) { Throwable throwable = ExceptionUtils.getRootCause(dve.getCause()); handleDataIntegrityIssues(command, throwable, dve); return CommandProcessingResult.empty(); } }
From source file:com.gst.portfolio.group.service.GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
private CommandProcessingResult createGroupingType(final JsonCommand command, final GroupTypes groupingType, final Long centerId) { try {//from www . ja v a 2s. c om final String accountNo = command .stringValueOfParameterNamed(GroupingTypesApiConstants.accountNoParamName); final String name = command.stringValueOfParameterNamed(GroupingTypesApiConstants.nameParamName); final String externalId = command .stringValueOfParameterNamed(GroupingTypesApiConstants.externalIdParamName); final AppUser currentUser = this.context.authenticatedUser(); Long officeId = null; Group parentGroup = null; if (centerId == null) { officeId = command.longValueOfParameterNamed(GroupingTypesApiConstants.officeIdParamName); } else { parentGroup = this.groupRepository.findOneWithNotFoundDetection(centerId); officeId = parentGroup.officeId(); } final Office groupOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(officeId); final LocalDate activationDate = command .localDateValueOfParameterNamed(GroupingTypesApiConstants.activationDateParamName); final GroupLevel groupLevel = this.groupLevelRepository.findOne(groupingType.getId()); validateOfficeOpeningDateisAfterGroupOrCenterOpeningDate(groupOffice, groupLevel, activationDate); Staff staff = null; final Long staffId = command.longValueOfParameterNamed(GroupingTypesApiConstants.staffIdParamName); if (staffId != null) { staff = this.staffRepository.findByOfficeHierarchyWithNotFoundDetection(staffId, groupOffice.getHierarchy()); } final Set<Client> clientMembers = assembleSetOfClients(officeId, command); final Set<Group> groupMembers = assembleSetOfChildGroups(officeId, command); final boolean active = command .booleanPrimitiveValueOfParameterNamed(GroupingTypesApiConstants.activeParamName); LocalDate submittedOnDate = new LocalDate(); if (active && submittedOnDate.isAfter(activationDate)) { submittedOnDate = activationDate; } if (command.hasParameter(GroupingTypesApiConstants.submittedOnDateParamName)) { submittedOnDate = command .localDateValueOfParameterNamed(GroupingTypesApiConstants.submittedOnDateParamName); } final Group newGroup = Group.newGroup(groupOffice, staff, parentGroup, groupLevel, name, externalId, active, activationDate, clientMembers, groupMembers, submittedOnDate, currentUser, accountNo); boolean rollbackTransaction = false; if (newGroup.isActive()) { this.groupRepository.save(newGroup); // validate Group creation rules for Group if (newGroup.isGroup()) { validateGroupRulesBeforeActivation(newGroup); } if (newGroup.isCenter()) { final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateCenter(null).build(); rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser); } else { final CommandWrapper commandWrapper = new CommandWrapperBuilder().activateGroup(null).build(); rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser); } } if (!newGroup.isCenter() && newGroup.hasActiveClients()) { final CommandWrapper commandWrapper = new CommandWrapperBuilder() .associateClientsToGroup(newGroup.getId()).build(); rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, currentUser); } // pre-save to generate id for use in group hierarchy this.groupRepository.save(newGroup); /* * Generate hierarchy for a new center/group and all the child * groups if they exist */ newGroup.generateHierarchy(); /* Generate account number if required */ generateAccountNumberIfRequired(newGroup); this.groupRepository.saveAndFlush(newGroup); newGroup.captureStaffHistoryDuringCenterCreation(staff, activationDate); if (newGroup.isGroup()) { if (command.parameterExists(GroupingTypesApiConstants.datatables)) { this.entityDatatableChecksWritePlatformService.saveDatatables( StatusEnum.CREATE.getCode().longValue(), EntityTables.GROUP.getName(), newGroup.getId(), null, command.arrayOfParameterNamed(GroupingTypesApiConstants.datatables)); } this.entityDatatableChecksWritePlatformService.runTheCheck(newGroup.getId(), EntityTables.GROUP.getName(), StatusEnum.CREATE.getCode().longValue(), EntityTables.GROUP.getForeignKeyColumnNameOnDatatable()); } return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withOfficeId(groupOffice.getId()) // .withGroupId(newGroup.getId()) // .withEntityId(newGroup.getId()) // .setRollbackTransaction(rollbackTransaction)// .build(); } catch (final DataIntegrityViolationException dve) { handleGroupDataIntegrityIssues(command, dve.getMostSpecificCause(), dve, groupingType); return CommandProcessingResult.empty(); } catch (final PersistenceException dve) { Throwable throwable = ExceptionUtils.getRootCause(dve.getCause()); handleGroupDataIntegrityIssues(command, throwable, dve, groupingType); return CommandProcessingResult.empty(); } }
From source file:com.gst.portfolio.loanaccount.service.LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
private void saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) { try {/*from w w w . j a va2s . c om*/ List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments(); for (LoanRepaymentScheduleInstallment installment : installments) { if (installment.getId() == null) { this.repaymentScheduleInstallmentRepository.save(installment); } } this.loanRepositoryWrapper.saveAndFlush(loan); } catch (final DataIntegrityViolationException e) { final Throwable realCause = e.getCause(); final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource("loan.application"); if (realCause.getMessage().toLowerCase().contains("external_id_unique")) { baseDataValidator.reset().parameter("externalId").failWithCode("value.must.be.unique"); } if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); } } }
From source file:com.gst.portfolio.loanaccount.service.LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
@Transactional @Override//from www.ja v a 2 s .com public CommandProcessingResult submitApplication(final JsonCommand command) { try { final AppUser currentUser = getAppUserIfPresent(); boolean isMeetingMandatoryForJLGLoans = configurationDomainService.isMeetingMandatoryForJLGLoans(); final Long productId = this.fromJsonHelper.extractLongNamed("productId", command.parsedJson()); final LoanProduct loanProduct = this.loanProductRepository.findOne(productId); if (loanProduct == null) { throw new LoanProductNotFoundException(productId); } final Long clientId = this.fromJsonHelper.extractLongNamed("clientId", command.parsedJson()); if (clientId != null) { Client client = this.clientRepository.findOneWithNotFoundDetection(clientId); officeSpecificLoanProductValidation(productId, client.getOffice().getId()); } final Long groupId = this.fromJsonHelper.extractLongNamed("groupId", command.parsedJson()); if (groupId != null) { Group group = this.groupRepository.findOneWithNotFoundDetection(groupId); officeSpecificLoanProductValidation(productId, group.getOffice().getId()); } this.fromApiJsonDeserializer.validateForCreate(command.json(), isMeetingMandatoryForJLGLoans, loanProduct); final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource("loan"); if (loanProduct.useBorrowerCycle()) { Integer cycleNumber = 0; if (clientId != null) { cycleNumber = this.loanReadPlatformService.retriveLoanCounter(clientId, loanProduct.getId()); } else if (groupId != null) { cycleNumber = this.loanReadPlatformService.retriveLoanCounter(groupId, AccountType.GROUP.getValue(), loanProduct.getId()); } this.loanProductCommandFromApiJsonDeserializer.validateMinMaxConstraints(command.parsedJson(), baseDataValidator, loanProduct, cycleNumber); } else { this.loanProductCommandFromApiJsonDeserializer.validateMinMaxConstraints(command.parsedJson(), baseDataValidator, loanProduct); } if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } final Loan newLoanApplication = this.loanAssembler.assembleFrom(command, currentUser); validateSubmittedOnDate(newLoanApplication); final LoanProductRelatedDetail productRelatedDetail = newLoanApplication.repaymentScheduleDetail(); if (loanProduct.getLoanProductConfigurableAttributes() != null) { updateProductRelatedDetails(productRelatedDetail, newLoanApplication); } this.fromApiJsonDeserializer.validateLoanTermAndRepaidEveryValues(newLoanApplication.getTermFrequency(), newLoanApplication.getTermPeriodFrequencyType(), productRelatedDetail.getNumberOfRepayments(), productRelatedDetail.getRepayEvery(), productRelatedDetail.getRepaymentPeriodFrequencyType().getValue(), newLoanApplication); if (loanProduct.canUseForTopup() && clientId != null) { final Boolean isTopup = command.booleanObjectValueOfParameterNamed(LoanApiConstants.isTopup); if (null == isTopup) { newLoanApplication.setIsTopup(false); } else { newLoanApplication.setIsTopup(isTopup); } if (newLoanApplication.isTopup()) { final Long loanIdToClose = command.longValueOfParameterNamed(LoanApiConstants.loanIdToClose); final Loan loanToClose = this.loanRepositoryWrapper .findNonClosedLoanThatBelongsToClient(loanIdToClose, clientId); if (loanToClose == null) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.loanIdToClose.no.active.loan.associated.to.client.found", "loanIdToClose is invalid, No Active Loan associated with the given Client ID found."); } if (loanToClose.isMultiDisburmentLoan() && !loanToClose.isInterestRecalculationEnabledForProduct()) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.topup.on.multi.tranche.loan.without.interest.recalculation.not.supported", "Topup on loan with multi-tranche disbursal and without interest recalculation is not supported."); } final LocalDate disbursalDateOfLoanToClose = loanToClose.getDisbursementDate(); if (!newLoanApplication.getSubmittedOnDate().isAfter(disbursalDateOfLoanToClose)) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.submitted.date.should.be.after.topup.loan.disbursal.date", "Submitted date of this loan application " + newLoanApplication.getSubmittedOnDate() + " should be after the disbursed date of loan to be closed " + disbursalDateOfLoanToClose); } if (!loanToClose.getCurrencyCode().equals(newLoanApplication.getCurrencyCode())) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.to.be.closed.has.different.currency", "loanIdToClose is invalid, Currency code is different."); } final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate(); if (!newLoanApplication.getDisbursementDate().isAfter(lastUserTransactionOnLoanToClose)) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed", "Disbursal date of this loan application " + newLoanApplication.getDisbursementDate() + " should be after last transaction date of loan to be closed " + lastUserTransactionOnLoanToClose); } BigDecimal loanOutstanding = this.loanReadPlatformService .retrieveLoanPrePaymentTemplate(loanIdToClose, newLoanApplication.getDisbursementDate()) .getAmount(); final BigDecimal firstDisbursalAmount = newLoanApplication.getFirstDisbursalAmount(); if (loanOutstanding.compareTo(firstDisbursalAmount) > 0) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.amount.less.than.outstanding.of.loan.to.be.closed", "Topup loan amount should be greater than outstanding amount of loan to be closed."); } final LoanTopupDetails topupDetails = new LoanTopupDetails(newLoanApplication, loanIdToClose); newLoanApplication.setTopupLoanDetails(topupDetails); } } this.loanRepositoryWrapper.save(newLoanApplication); if (loanProduct.isInterestRecalculationEnabled()) { this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(newLoanApplication); createAndPersistCalendarInstanceForInterestRecalculation(newLoanApplication); } if (newLoanApplication.isAccountNumberRequiresAutoGeneration()) { final AccountNumberFormat accountNumberFormat = this.accountNumberFormatRepository .findByAccountType(EntityAccountType.LOAN); newLoanApplication.updateAccountNo( this.accountNumberGenerator.generate(newLoanApplication, accountNumberFormat)); this.loanRepositoryWrapper.save(newLoanApplication); } final String submittedOnNote = command.stringValueOfParameterNamed("submittedOnNote"); if (StringUtils.isNotBlank(submittedOnNote)) { final Note note = Note.loanNote(newLoanApplication, submittedOnNote); this.noteRepository.save(note); } // Save calendar instance final Long calendarId = command.longValueOfParameterNamed("calendarId"); Calendar calendar = null; if (calendarId != null && calendarId != 0) { calendar = this.calendarRepository.findOne(calendarId); if (calendar == null) { throw new CalendarNotFoundException(calendarId); } final CalendarInstance calendarInstance = new CalendarInstance(calendar, newLoanApplication.getId(), CalendarEntityType.LOANS.getValue()); this.calendarInstanceRepository.save(calendarInstance); } else { final LoanApplicationTerms loanApplicationTerms = this.loanScheduleAssembler .assembleLoanTerms(command.parsedJson()); final Integer repaymentFrequencyNthDayType = command .integerValueOfParameterNamed("repaymentFrequencyNthDayType"); if (loanApplicationTerms.getRepaymentPeriodFrequencyType() == PeriodFrequencyType.MONTHS && repaymentFrequencyNthDayType != null) { final String title = "loan_schedule_" + newLoanApplication.getId(); LocalDate calendarStartDate = loanApplicationTerms.getRepaymentsStartingFromLocalDate(); if (calendarStartDate == null) calendarStartDate = loanApplicationTerms.getExpectedDisbursementDate(); final CalendarFrequencyType calendarFrequencyType = CalendarFrequencyType.MONTHLY; final Integer frequency = loanApplicationTerms.getRepaymentEvery(); final Integer repeatsOnDay = loanApplicationTerms.getWeekDayType().getValue(); final Integer repeatsOnNthDayOfMonth = loanApplicationTerms.getNthDay(); final Integer calendarEntityType = CalendarEntityType.LOANS.getValue(); final Calendar loanCalendar = Calendar.createRepeatingCalendar(title, calendarStartDate, CalendarType.COLLECTION.getValue(), calendarFrequencyType, frequency, repeatsOnDay, repeatsOnNthDayOfMonth); this.calendarRepository.save(loanCalendar); final CalendarInstance calendarInstance = CalendarInstance.from(loanCalendar, newLoanApplication.getId(), calendarEntityType); this.calendarInstanceRepository.save(calendarInstance); } } // Save linked account information final Long savingsAccountId = command.longValueOfParameterNamed("linkAccountId"); if (savingsAccountId != null) { final SavingsAccount savingsAccount = this.savingsAccountAssembler.assembleFrom(savingsAccountId); this.fromApiJsonDeserializer.validatelinkedSavingsAccount(savingsAccount, newLoanApplication); boolean isActive = true; final AccountAssociations accountAssociations = AccountAssociations.associateSavingsAccount( newLoanApplication, savingsAccount, AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue(), isActive); this.accountAssociationsRepository.save(accountAssociations); } if (command.parameterExists(LoanApiConstants.datatables)) { this.entityDatatableChecksWritePlatformService.saveDatatables( StatusEnum.CREATE.getCode().longValue(), EntityTables.LOAN.getName(), newLoanApplication.getId(), newLoanApplication.productId(), command.arrayOfParameterNamed(LoanApiConstants.datatables)); } this.entityDatatableChecksWritePlatformService.runTheCheckForProduct(newLoanApplication.getId(), EntityTables.LOAN.getName(), StatusEnum.CREATE.getCode().longValue(), EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), newLoanApplication.productId()); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withEntityId(newLoanApplication.getId()) // .withOfficeId(newLoanApplication.getOfficeId()) // .withClientId(newLoanApplication.getClientId()) // .withGroupId(newLoanApplication.getGroupId()) // .withLoanId(newLoanApplication.getId()) // .build(); } catch (final DataIntegrityViolationException dve) { handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); return CommandProcessingResult.empty(); } catch (final PersistenceException dve) { Throwable throwable = ExceptionUtils.getRootCause(dve.getCause()); handleDataIntegrityIssues(command, throwable, dve); return CommandProcessingResult.empty(); } }
From source file:com.gst.infrastructure.dataqueries.service.ReadWriteNonCoreDataServiceImpl.java
@Transactional @Override/*from w ww . j a v a2 s . c om*/ public void deleteDatatable(final String datatableName) { try { this.context.authenticatedUser(); if (!isRegisteredDataTable(datatableName)) { throw new DatatableNotFoundException(datatableName); } validateDatatableName(datatableName); assertDataTableEmpty(datatableName); deregisterDatatable(datatableName); String[] sqlArray = null; if (this.configurationDomainService.isConstraintApproachEnabledForDatatables()) { final String deleteColumnCodeSql = "delete from x_table_column_code_mappings where column_alias_name like'" + datatableName.toLowerCase().replaceAll("\\s", "_") + "_%'"; sqlArray = new String[2]; sqlArray[1] = deleteColumnCodeSql; } else { sqlArray = new String[1]; } final String sql = "DROP TABLE `" + datatableName + "`"; sqlArray[0] = sql; this.jdbcTemplate.batchUpdate(sqlArray); } catch (final DataIntegrityViolationException e) { final Throwable realCause = e.getCause(); final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource("datatable"); if (realCause.getMessage().contains("Unknown table")) { baseDataValidator.reset().parameter("datatableName").failWithCode("does.not.exist"); } throwExceptionIfValidationWarningsExist(dataValidationErrors); } }
From source file:com.gst.infrastructure.dataqueries.service.ReadWriteNonCoreDataServiceImpl.java
@Transactional private void _registerDataTable(final String applicationTableName, final String dataTableName, final Integer category, final String permissionsSql) { validateAppTable(applicationTableName); assertDataTableExists(dataTableName); final String registerDatatableSql = "insert into x_registered_table (registered_table_name, application_table_name,category) values ('" + dataTableName + "', '" + applicationTableName + "', '" + category + "')"; try {/*from ww w.j av a 2 s. c om*/ final String[] sqlArray = { registerDatatableSql, permissionsSql }; this.jdbcTemplate.batchUpdate(sqlArray); // add the registered table to the config if it is a ppi if (this.isSurveyCategory(category)) { this.jdbcTemplate.execute("insert into c_configuration (name, value, enabled ) values('" + dataTableName + "', '0','0')"); } } catch (final DataIntegrityViolationException dve) { final Throwable cause = dve.getCause(); final Throwable realCause = dve.getMostSpecificCause(); // even if duplicate is only due to permission duplicate, okay to // show duplicate datatable error msg if (realCause.getMessage().contains("Duplicate entry") || cause.getMessage().contains("Duplicate entry")) { throw new PlatformDataIntegrityException("error.msg.datatable.registered", "Datatable `" + dataTableName + "` is already registered against an application table.", "dataTableName", dataTableName); } logAsErrorUnexpectedDataIntegrityException(dve); throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue", "Unknown data integrity issue with resource."); } catch (final PersistenceException dve) { final Throwable cause = dve.getCause(); if (cause.getMessage().contains("Duplicate entry")) { throw new PlatformDataIntegrityException("error.msg.datatable.registered", "Datatable `" + dataTableName + "` is already registered against an application table.", "dataTableName", dataTableName); } logAsErrorUnexpectedDataIntegrityException(dve); throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue", "Unknown data integrity issue with resource."); } }
From source file:com.gst.infrastructure.dataqueries.service.ReadWriteNonCoreDataServiceImpl.java
@Transactional @Override/* w w w.j a v a 2 s .c o m*/ public CommandProcessingResult createDatatable(final JsonCommand command) { String datatableName = null; try { this.context.authenticatedUser(); this.fromApiJsonDeserializer.validateForCreate(command.json()); final JsonElement element = this.fromJsonHelper.parse(command.json()); final JsonArray columns = this.fromJsonHelper.extractJsonArrayNamed("columns", element); datatableName = this.fromJsonHelper.extractStringNamed("datatableName", element); final String apptableName = this.fromJsonHelper.extractStringNamed("apptableName", element); Boolean multiRow = this.fromJsonHelper.extractBooleanNamed("multiRow", element); /*** * In cases of tables storing hierarchical entities (like m_group), * different entities would end up being stored in the same table. * * Ex: Centers are a specific type of group, add abstractions for * the same ***/ final String actualAppTableName = mapToActualAppTable(apptableName); if (multiRow == null) { multiRow = false; } validateDatatableName(datatableName); validateAppTable(apptableName); final boolean isConstraintApproach = this.configurationDomainService .isConstraintApproachEnabledForDatatables(); final String fkColumnName = apptableName.substring(2) + "_id"; final String dataTableNameAlias = datatableName.toLowerCase().replaceAll("\\s", "_"); final String fkName = dataTableNameAlias + "_" + fkColumnName; StringBuilder sqlBuilder = new StringBuilder(); final StringBuilder constrainBuilder = new StringBuilder(); final Map<String, Long> codeMappings = new HashMap<>(); sqlBuilder = sqlBuilder.append("CREATE TABLE `" + datatableName + "` ("); if (multiRow) { sqlBuilder = sqlBuilder.append("`id` BIGINT(20) NOT NULL AUTO_INCREMENT, ") .append("`" + fkColumnName + "` BIGINT(20) NOT NULL, "); } else { sqlBuilder = sqlBuilder.append("`" + fkColumnName + "` BIGINT(20) NOT NULL, "); } for (final JsonElement column : columns) { parseDatatableColumnObjectForCreate(column.getAsJsonObject(), sqlBuilder, constrainBuilder, dataTableNameAlias, codeMappings, isConstraintApproach); } // Remove trailing comma and space sqlBuilder = sqlBuilder.delete(sqlBuilder.length() - 2, sqlBuilder.length()); if (multiRow) { sqlBuilder = sqlBuilder.append(", PRIMARY KEY (`id`)") .append(", KEY `fk_" + apptableName.substring(2) + "_id` (`" + fkColumnName + "`)") .append(", CONSTRAINT `fk_" + fkName + "` ").append("FOREIGN KEY (`" + fkColumnName + "`) ") .append("REFERENCES `" + actualAppTableName + "` (`id`)"); } else { sqlBuilder = sqlBuilder.append(", PRIMARY KEY (`" + fkColumnName + "`)") .append(", CONSTRAINT `fk_" + fkName + "` ").append("FOREIGN KEY (`" + fkColumnName + "`) ") .append("REFERENCES `" + actualAppTableName + "` (`id`)"); } sqlBuilder.append(constrainBuilder); sqlBuilder = sqlBuilder.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8;"); this.jdbcTemplate.execute(sqlBuilder.toString()); registerDatatable(datatableName, apptableName); registerColumnCodeMapping(codeMappings); } catch (final DataIntegrityViolationException e) { final Throwable realCause = e.getCause(); final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource("datatable"); if (realCause.getMessage().toLowerCase().contains("duplicate column name")) { baseDataValidator.reset().parameter("name").failWithCode("duplicate.column.name"); } else if (realCause.getMessage().contains("Table") && realCause.getMessage().contains("already exists")) { baseDataValidator.reset().parameter("datatableName").value(datatableName) .failWithCode("datatable.already.exists"); } else if (realCause.getMessage().contains("Column") && realCause.getMessage().contains("big")) { baseDataValidator.reset().parameter("column").failWithCode("length.too.big"); } else if (realCause.getMessage().contains("Row") && realCause.getMessage().contains("large")) { baseDataValidator.reset().parameter("row").failWithCode("size.too.large"); } throwExceptionIfValidationWarningsExist(dataValidationErrors); } catch (final PersistenceException | BadSqlGrammarException ee) { Throwable realCause = ExceptionUtils.getRootCause(ee.getCause()); final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource("datatable"); if (realCause.getMessage().toLowerCase().contains("duplicate column name")) { baseDataValidator.reset().parameter("name").failWithCode("duplicate.column.name"); } else if (realCause.getMessage().contains("Table") && realCause.getMessage().contains("already exists")) { baseDataValidator.reset().parameter("datatableName").value(datatableName) .failWithCode("datatable.already.exists"); } else if (realCause.getMessage().contains("Column") && realCause.getMessage().contains("big")) { baseDataValidator.reset().parameter("column").failWithCode("length.too.big"); } else if (realCause.getMessage().contains("Row") && realCause.getMessage().contains("large")) { baseDataValidator.reset().parameter("row").failWithCode("size.too.large"); } throwExceptionIfValidationWarningsExist(dataValidationErrors); } return new CommandProcessingResultBuilder().withCommandId(command.commandId()) .withResourceIdAsString(datatableName).build(); }
From source file:com.gst.portfolio.loanaccount.service.LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
@Transactional @Override// www .jav a2 s .c o m public CommandProcessingResult modifyApplication(final Long loanId, final JsonCommand command) { try { AppUser currentUser = getAppUserIfPresent(); final Loan existingLoanApplication = retrieveLoanBy(loanId); if (!existingLoanApplication.isSubmittedAndPendingApproval()) { throw new LoanApplicationNotInSubmittedAndPendingApprovalStateCannotBeModified(loanId); } final String productIdParamName = "productId"; LoanProduct newLoanProduct = null; if (command.isChangeInLongParameterNamed(productIdParamName, existingLoanApplication.loanProduct().getId())) { final Long productId = command.longValueOfParameterNamed(productIdParamName); newLoanProduct = this.loanProductRepository.findOne(productId); if (newLoanProduct == null) { throw new LoanProductNotFoundException(productId); } } LoanProduct loanProductForValidations = newLoanProduct == null ? existingLoanApplication.loanProduct() : newLoanProduct; this.fromApiJsonDeserializer.validateForModify(command.json(), loanProductForValidations, existingLoanApplication); checkClientOrGroupActive(existingLoanApplication); final Set<LoanCharge> existingCharges = existingLoanApplication.charges(); Map<Long, LoanChargeData> chargesMap = new HashMap<>(); for (LoanCharge charge : existingCharges) { LoanChargeData chargeData = new LoanChargeData(charge.getId(), charge.getDueLocalDate(), charge.amountOrPercentage()); chargesMap.put(charge.getId(), chargeData); } List<LoanDisbursementDetails> disbursementDetails = this.loanUtilService .fetchDisbursementData(command.parsedJson().getAsJsonObject()); /** * Stores all charges which are passed in during modify loan * application **/ final Set<LoanCharge> possiblyModifedLoanCharges = this.loanChargeAssembler .fromParsedJson(command.parsedJson(), disbursementDetails); /** Boolean determines if any charge has been modified **/ boolean isChargeModified = false; Set<Charge> newTrancheChages = this.loanChargeAssembler.getNewLoanTrancheCharges(command.parsedJson()); for (Charge charge : newTrancheChages) { existingLoanApplication.addTrancheLoanCharge(charge); } /** * If there are any charges already present, which are now not * passed in as a part of the request, deem the charges as modified **/ if (!possiblyModifedLoanCharges.isEmpty()) { if (!possiblyModifedLoanCharges.containsAll(existingCharges)) { isChargeModified = true; } } /** * If any new charges are added or values of existing charges are * modified **/ for (LoanCharge loanCharge : possiblyModifedLoanCharges) { if (loanCharge.getId() == null) { isChargeModified = true; } else { LoanChargeData chargeData = chargesMap.get(loanCharge.getId()); if (loanCharge.amountOrPercentage().compareTo(chargeData.amountOrPercentage()) != 0 || (loanCharge.isSpecifiedDueDate() && !loanCharge.getDueLocalDate().equals(chargeData.getDueDate()))) { isChargeModified = true; } } } final Set<LoanCollateral> possiblyModifedLoanCollateralItems = this.loanCollateralAssembler .fromParsedJson(command.parsedJson()); final Map<String, Object> changes = existingLoanApplication.loanApplicationModification(command, possiblyModifedLoanCharges, possiblyModifedLoanCollateralItems, this.aprCalculator, isChargeModified); if (changes.containsKey("expectedDisbursementDate")) { this.loanAssembler.validateExpectedDisbursementForHolidayAndNonWorkingDay(existingLoanApplication); } final String clientIdParamName = "clientId"; if (changes.containsKey(clientIdParamName)) { final Long clientId = command.longValueOfParameterNamed(clientIdParamName); final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId); if (client.isNotActive()) { throw new ClientNotActiveException(clientId); } existingLoanApplication.updateClient(client); } final String groupIdParamName = "groupId"; if (changes.containsKey(groupIdParamName)) { final Long groupId = command.longValueOfParameterNamed(groupIdParamName); final Group group = this.groupRepository.findOneWithNotFoundDetection(groupId); if (group.isNotActive()) { throw new GroupNotActiveException(groupId); } existingLoanApplication.updateGroup(group); } if (newLoanProduct != null) { existingLoanApplication.updateLoanProduct(newLoanProduct); if (!changes.containsKey("interestRateFrequencyType")) { existingLoanApplication.updateInterestRateFrequencyType(); } final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource("loan"); if (newLoanProduct.useBorrowerCycle()) { final Long clientId = this.fromJsonHelper.extractLongNamed("clientId", command.parsedJson()); final Long groupId = this.fromJsonHelper.extractLongNamed("groupId", command.parsedJson()); Integer cycleNumber = 0; if (clientId != null) { cycleNumber = this.loanReadPlatformService.retriveLoanCounter(clientId, newLoanProduct.getId()); } else if (groupId != null) { cycleNumber = this.loanReadPlatformService.retriveLoanCounter(groupId, AccountType.GROUP.getValue(), newLoanProduct.getId()); } this.loanProductCommandFromApiJsonDeserializer.validateMinMaxConstraints(command.parsedJson(), baseDataValidator, newLoanProduct, cycleNumber); } else { this.loanProductCommandFromApiJsonDeserializer.validateMinMaxConstraints(command.parsedJson(), baseDataValidator, newLoanProduct); } if (newLoanProduct.isLinkedToFloatingInterestRate()) { existingLoanApplication.getLoanProductRelatedDetail().updateForFloatingInterestRates(); } else { existingLoanApplication.setInterestRateDifferential(null); existingLoanApplication.setIsFloatingInterestRate(null); } if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } existingLoanApplication.updateIsInterestRecalculationEnabled(); validateSubmittedOnDate(existingLoanApplication); final LoanProductRelatedDetail productRelatedDetail = existingLoanApplication.repaymentScheduleDetail(); if (existingLoanApplication.loanProduct().getLoanProductConfigurableAttributes() != null) { updateProductRelatedDetails(productRelatedDetail, existingLoanApplication); } if (existingLoanApplication.getLoanProduct().canUseForTopup() && existingLoanApplication.getClientId() != null) { final Boolean isTopup = command.booleanObjectValueOfParameterNamed(LoanApiConstants.isTopup); if (command.isChangeInBooleanParameterNamed(LoanApiConstants.isTopup, existingLoanApplication.isTopup())) { existingLoanApplication.setIsTopup(isTopup); changes.put(LoanApiConstants.isTopup, isTopup); } if (existingLoanApplication.isTopup()) { final Long loanIdToClose = command.longValueOfParameterNamed(LoanApiConstants.loanIdToClose); LoanTopupDetails existingLoanTopupDetails = existingLoanApplication.getTopupLoanDetails(); if (existingLoanTopupDetails == null || (existingLoanTopupDetails != null && existingLoanTopupDetails.getLoanIdToClose() != loanIdToClose) || changes.containsKey("submittedOnDate") || changes.containsKey("expectedDisbursementDate") || changes.containsKey("principal") || changes.containsKey(LoanApiConstants.disbursementDataParameterName)) { Long existingLoanIdToClose = null; if (existingLoanTopupDetails != null) { existingLoanIdToClose = existingLoanTopupDetails.getLoanIdToClose(); } final Loan loanToClose = this.loanRepositoryWrapper.findNonClosedLoanThatBelongsToClient( loanIdToClose, existingLoanApplication.getClientId()); if (loanToClose == null) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.loanIdToClose.no.active.loan.associated.to.client.found", "loanIdToClose is invalid, No Active Loan associated with the given Client ID found."); } if (loanToClose.isMultiDisburmentLoan() && !loanToClose.isInterestRecalculationEnabledForProduct()) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.topup.on.multi.tranche.loan.without.interest.recalculation.not.supported", "Topup on loan with multi-tranche disbursal and without interest recalculation is not supported."); } final LocalDate disbursalDateOfLoanToClose = loanToClose.getDisbursementDate(); if (!existingLoanApplication.getSubmittedOnDate().isAfter(disbursalDateOfLoanToClose)) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.submitted.date.should.be.after.topup.loan.disbursal.date", "Submitted date of this loan application " + existingLoanApplication.getSubmittedOnDate() + " should be after the disbursed date of loan to be closed " + disbursalDateOfLoanToClose); } if (!loanToClose.getCurrencyCode().equals(existingLoanApplication.getCurrencyCode())) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.to.be.closed.has.different.currency", "loanIdToClose is invalid, Currency code is different."); } final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate(); if (!existingLoanApplication.getDisbursementDate() .isAfter(lastUserTransactionOnLoanToClose)) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed", "Disbursal date of this loan application " + existingLoanApplication.getDisbursementDate() + " should be after last transaction date of loan to be closed " + lastUserTransactionOnLoanToClose); } BigDecimal loanOutstanding = this.loanReadPlatformService.retrieveLoanPrePaymentTemplate( loanIdToClose, existingLoanApplication.getDisbursementDate()).getAmount(); final BigDecimal firstDisbursalAmount = existingLoanApplication.getFirstDisbursalAmount(); if (loanOutstanding.compareTo(firstDisbursalAmount) > 0) { throw new GeneralPlatformDomainRuleException( "error.msg.loan.amount.less.than.outstanding.of.loan.to.be.closed", "Topup loan amount should be greater than outstanding amount of loan to be closed."); } if (existingLoanIdToClose != loanIdToClose) { final LoanTopupDetails topupDetails = new LoanTopupDetails(existingLoanApplication, loanIdToClose); existingLoanApplication.setTopupLoanDetails(topupDetails); changes.put(LoanApiConstants.loanIdToClose, loanIdToClose); } } } else { existingLoanApplication.setTopupLoanDetails(null); } } else { if (existingLoanApplication.isTopup()) { existingLoanApplication.setIsTopup(false); existingLoanApplication.setTopupLoanDetails(null); changes.put(LoanApiConstants.isTopup, false); } } final String fundIdParamName = "fundId"; if (changes.containsKey(fundIdParamName)) { final Long fundId = command.longValueOfParameterNamed(fundIdParamName); final Fund fund = this.loanAssembler.findFundByIdIfProvided(fundId); existingLoanApplication.updateFund(fund); } final String loanPurposeIdParamName = "loanPurposeId"; if (changes.containsKey(loanPurposeIdParamName)) { final Long loanPurposeId = command.longValueOfParameterNamed(loanPurposeIdParamName); final CodeValue loanPurpose = this.loanAssembler.findCodeValueByIdIfProvided(loanPurposeId); existingLoanApplication.updateLoanPurpose(loanPurpose); } final String loanOfficerIdParamName = "loanOfficerId"; if (changes.containsKey(loanOfficerIdParamName)) { final Long loanOfficerId = command.longValueOfParameterNamed(loanOfficerIdParamName); final Staff newValue = this.loanAssembler.findLoanOfficerByIdIfProvided(loanOfficerId); existingLoanApplication.updateLoanOfficerOnLoanApplication(newValue); } final String strategyIdParamName = "transactionProcessingStrategyId"; if (changes.containsKey(strategyIdParamName)) { final Long strategyId = command.longValueOfParameterNamed(strategyIdParamName); final LoanTransactionProcessingStrategy strategy = this.loanAssembler .findStrategyByIdIfProvided(strategyId); existingLoanApplication.updateTransactionProcessingStrategy(strategy); } final String collateralParamName = "collateral"; if (changes.containsKey(collateralParamName)) { final Set<LoanCollateral> loanCollateral = this.loanCollateralAssembler .fromParsedJson(command.parsedJson()); existingLoanApplication.updateLoanCollateral(loanCollateral); } final String chargesParamName = "charges"; if (changes.containsKey(chargesParamName)) { existingLoanApplication.updateLoanCharges(possiblyModifedLoanCharges); } if (changes.containsKey("recalculateLoanSchedule")) { changes.remove("recalculateLoanSchedule"); final JsonElement parsedQuery = this.fromJsonHelper.parse(command.json()); final JsonQuery query = JsonQuery.from(command.json(), parsedQuery, this.fromJsonHelper); final LoanScheduleModel loanSchedule = this.calculationPlatformService.calculateLoanSchedule(query, false); existingLoanApplication.updateLoanSchedule(loanSchedule, currentUser); existingLoanApplication.recalculateAllCharges(); } this.fromApiJsonDeserializer.validateLoanTermAndRepaidEveryValues( existingLoanApplication.getTermFrequency(), existingLoanApplication.getTermPeriodFrequencyType(), productRelatedDetail.getNumberOfRepayments(), productRelatedDetail.getRepayEvery(), productRelatedDetail.getRepaymentPeriodFrequencyType().getValue(), existingLoanApplication); saveAndFlushLoanWithDataIntegrityViolationChecks(existingLoanApplication); final String submittedOnNote = command.stringValueOfParameterNamed("submittedOnNote"); if (StringUtils.isNotBlank(submittedOnNote)) { final Note note = Note.loanNote(existingLoanApplication, submittedOnNote); this.noteRepository.save(note); } final Long calendarId = command.longValueOfParameterNamed("calendarId"); Calendar calendar = null; if (calendarId != null && calendarId != 0) { calendar = this.calendarRepository.findOne(calendarId); if (calendar == null) { throw new CalendarNotFoundException(calendarId); } } final List<CalendarInstance> ciList = (List<CalendarInstance>) this.calendarInstanceRepository .findByEntityIdAndEntityTypeId(loanId, CalendarEntityType.LOANS.getValue()); if (calendar != null) { // For loans, allow to attach only one calendar instance per // loan if (ciList != null && !ciList.isEmpty()) { final CalendarInstance calendarInstance = ciList.get(0); final boolean isCalendarAssociatedWithEntity = this.calendarReadPlatformService .isCalendarAssociatedWithEntity(calendarInstance.getEntityId(), calendarInstance.getCalendar().getId(), CalendarEntityType.LOANS.getValue().longValue()); if (isCalendarAssociatedWithEntity) { this.calendarRepository.delete(calendarInstance.getCalendar()); } if (calendarInstance.getCalendar().getId() != calendar.getId()) { calendarInstance.updateCalendar(calendar); this.calendarInstanceRepository.saveAndFlush(calendarInstance); } } else { // attaching new calendar final CalendarInstance calendarInstance = new CalendarInstance(calendar, existingLoanApplication.getId(), CalendarEntityType.LOANS.getValue()); this.calendarInstanceRepository.save(calendarInstance); } } else { if (ciList != null && !ciList.isEmpty()) { final CalendarInstance existingCalendarInstance = ciList.get(0); final boolean isCalendarAssociatedWithEntity = this.calendarReadPlatformService .isCalendarAssociatedWithEntity(existingCalendarInstance.getEntityId(), existingCalendarInstance.getCalendar().getId(), CalendarEntityType.GROUPS.getValue().longValue()); if (isCalendarAssociatedWithEntity) { this.calendarInstanceRepository.delete(existingCalendarInstance); } } if (changes.containsKey("repaymentFrequencyNthDayType") || changes.containsKey("repaymentFrequencyDayOfWeekType")) { if (changes.get("repaymentFrequencyNthDayType") == null) { if (ciList != null && !ciList.isEmpty()) { final CalendarInstance calendarInstance = ciList.get(0); final boolean isCalendarAssociatedWithEntity = this.calendarReadPlatformService .isCalendarAssociatedWithEntity(calendarInstance.getEntityId(), calendarInstance.getCalendar().getId(), CalendarEntityType.LOANS.getValue().longValue()); if (isCalendarAssociatedWithEntity) { this.calendarInstanceRepository.delete(calendarInstance); this.calendarRepository.delete(calendarInstance.getCalendar()); } } } else { Integer repaymentFrequencyTypeInt = command .integerValueOfParameterNamed("repaymentFrequencyType"); if (repaymentFrequencyTypeInt != null) { if (PeriodFrequencyType .fromInt(repaymentFrequencyTypeInt) == PeriodFrequencyType.MONTHS) { final String title = "loan_schedule_" + existingLoanApplication.getId(); final Integer typeId = CalendarType.COLLECTION.getValue(); final CalendarFrequencyType repaymentFrequencyType = CalendarFrequencyType.MONTHLY; final Integer interval = command.integerValueOfParameterNamed("repaymentEvery"); LocalDate startDate = command .localDateValueOfParameterNamed("repaymentsStartingFromDate"); if (startDate == null) startDate = command.localDateValueOfParameterNamed("expectedDisbursementDate"); final Calendar newCalendar = Calendar.createRepeatingCalendar(title, startDate, typeId, repaymentFrequencyType, interval, (Integer) changes.get("repaymentFrequencyDayOfWeekType"), (Integer) changes.get("repaymentFrequencyNthDayType")); if (ciList != null && !ciList.isEmpty()) { final CalendarInstance calendarInstance = ciList.get(0); final boolean isCalendarAssociatedWithEntity = this.calendarReadPlatformService .isCalendarAssociatedWithEntity(calendarInstance.getEntityId(), calendarInstance.getCalendar().getId(), CalendarEntityType.LOANS.getValue().longValue()); if (isCalendarAssociatedWithEntity) { final Calendar existingCalendar = calendarInstance.getCalendar(); if (existingCalendar != null) { String existingRecurrence = existingCalendar.getRecurrence(); if (!existingRecurrence.equals(newCalendar.getRecurrence())) { existingCalendar.setRecurrence(newCalendar.getRecurrence()); this.calendarRepository.save(existingCalendar); } } } } else { this.calendarRepository.save(newCalendar); final Integer calendarEntityType = CalendarEntityType.LOANS.getValue(); final CalendarInstance calendarInstance = new CalendarInstance(newCalendar, existingLoanApplication.getId(), calendarEntityType); this.calendarInstanceRepository.save(calendarInstance); } } } } } } // Save linked account information final String linkAccountIdParamName = "linkAccountId"; final Long savingsAccountId = command.longValueOfParameterNamed(linkAccountIdParamName); AccountAssociations accountAssociations = this.accountAssociationsRepository.findByLoanIdAndType(loanId, AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue()); boolean isLinkedAccPresent = false; if (savingsAccountId == null) { if (accountAssociations != null) { if (this.fromJsonHelper.parameterExists(linkAccountIdParamName, command.parsedJson())) { this.accountAssociationsRepository.delete(accountAssociations); changes.put(linkAccountIdParamName, null); } else { isLinkedAccPresent = true; } } } else { isLinkedAccPresent = true; boolean isModified = false; if (accountAssociations == null) { isModified = true; } else { final SavingsAccount savingsAccount = accountAssociations.linkedSavingsAccount(); if (savingsAccount == null || !savingsAccount.getId().equals(savingsAccountId)) { isModified = true; } } if (isModified) { final SavingsAccount savingsAccount = this.savingsAccountAssembler .assembleFrom(savingsAccountId); this.fromApiJsonDeserializer.validatelinkedSavingsAccount(savingsAccount, existingLoanApplication); if (accountAssociations == null) { boolean isActive = true; accountAssociations = AccountAssociations.associateSavingsAccount(existingLoanApplication, savingsAccount, AccountAssociationType.LINKED_ACCOUNT_ASSOCIATION.getValue(), isActive); } else { accountAssociations.updateLinkedSavingsAccount(savingsAccount); } changes.put(linkAccountIdParamName, savingsAccountId); this.accountAssociationsRepository.save(accountAssociations); } } if (!isLinkedAccPresent) { final Set<LoanCharge> charges = existingLoanApplication.charges(); for (final LoanCharge loanCharge : charges) { if (loanCharge.getChargePaymentMode().isPaymentModeAccountTransfer()) { final String errorMessage = "one of the charges requires linked savings account for payment"; throw new LinkedAccountRequiredException("loanCharge", errorMessage); } } } if ((command.longValueOfParameterNamed(productIdParamName) != null) || (command.longValueOfParameterNamed(clientIdParamName) != null) || (command.longValueOfParameterNamed(groupIdParamName) != null)) { Long OfficeId = null; if (existingLoanApplication.getClient() != null) { OfficeId = existingLoanApplication.getClient().getOffice().getId(); } else if (existingLoanApplication.getGroup() != null) { OfficeId = existingLoanApplication.getGroup().getOffice().getId(); } officeSpecificLoanProductValidation(existingLoanApplication.getLoanProduct().getId(), OfficeId); } // updating loan interest recalculation details throwing null // pointer exception after saveAndFlush // http://stackoverflow.com/questions/17151757/hibernate-cascade-update-gives-null-pointer/17334374#17334374 this.loanRepositoryWrapper.save(existingLoanApplication); if (productRelatedDetail.isInterestRecalculationEnabled()) { this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(existingLoanApplication); if (changes.containsKey(LoanProductConstants.isInterestRecalculationEnabledParameterName)) { createAndPersistCalendarInstanceForInterestRecalculation(existingLoanApplication); } } return new CommandProcessingResultBuilder() // .withEntityId(loanId) // .withOfficeId(existingLoanApplication.getOfficeId()) // .withClientId(existingLoanApplication.getClientId()) // .withGroupId(existingLoanApplication.getGroupId()) // .withLoanId(existingLoanApplication.getId()) // .with(changes).build(); } catch (final DataIntegrityViolationException dve) { handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve); return CommandProcessingResult.empty(); } catch (final PersistenceException dve) { Throwable throwable = ExceptionUtils.getRootCause(dve.getCause()); handleDataIntegrityIssues(command, throwable, dve); return CommandProcessingResult.empty(); } }